Repository: silx-kit/h5web
Pull request #1362 (2023-02-03 13:00:41)

Make `aspect` prop of `VisCanvas` really consistent with matplotlib
In #1284 I say that the new `aspect` prop of `VisCanvas` works like matplotlib's [`Axes.set_aspect`](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_aspect.html), but this was not actually true. When passing a number, this number was used as the `visRatio` directly. The beahviour is now in line with matplotlib - i.e. for `aspect={2}`, we get:

![image](https://user-images.githubusercontent.com/2936402/216609695-ab884286-f4d0-42f5-8c6a-3e58f3fa81fa.png)



Patch:
diff --git a/packages/lib/src/vis/shared/VisCanvas.tsx b/packages/lib/src/vis/shared/VisCanvas.tsx
index f50d2a9e..15dda613 100644
--- a/packages/lib/src/vis/shared/VisCanvas.tsx
+++ b/packages/lib/src/vis/shared/VisCanvas.tsx
@@ -35,7 +35,11 @@ function VisCanvas(props: PropsWithChildren<Props>) {
     children,
   } = props;
 
-  const visRatio = getVisRatio(aspect, abscissaConfig, ordinateConfig);
+  const visRatio = getVisRatio(
+    aspect,
+    abscissaConfig.visDomain,
+    ordinateConfig.visDomain
+  );
 
   const axisOffsets = showAxes
     ? getAxisOffsets({
diff --git a/packages/lib/src/vis/utils.ts b/packages/lib/src/vis/utils.ts
index 61fe9122..50d0bfff 100644
--- a/packages/lib/src/vis/utils.ts
+++ b/packages/lib/src/vis/utils.ts
@@ -263,20 +263,20 @@ export function getCombinedDomain(
 
 export function getVisRatio(
   aspect: Aspect,
-  abscissaConfig: AxisConfig,
-  ordinateConfig: AxisConfig
+  abscissaDomain: Domain,
+  ordinateDomain: Domain
 ): number | undefined {
   if (aspect === 'auto') {
     return undefined;
   }
 
   if (aspect === 'equal') {
-    const [xMin, xMax] = abscissaConfig.visDomain;
-    const [yMin, yMax] = ordinateConfig.visDomain;
-    return Math.abs(xMax - xMin) / Math.abs(yMax - yMin);
+    return getVisRatio(1, abscissaDomain, ordinateDomain);
   }
 
-  return aspect;
+  const [xMin, xMax] = abscissaDomain;
+  const [yMin, yMax] = ordinateDomain;
+  return Math.abs(xMax - xMin) / Math.abs(yMax - yMin) / aspect;
 }
 
 export function getAxisOffsets(


Test patch:
diff --git a/packages/lib/src/vis/utils.test.ts b/packages/lib/src/vis/utils.test.ts
index 051b7d8f..89884f31 100644
--- a/packages/lib/src/vis/utils.test.ts
+++ b/packages/lib/src/vis/utils.test.ts
@@ -12,6 +12,7 @@ import {
   getCombinedDomain,
   clampBound,
   getAxisDomain,
+  getVisRatio,
 } from './utils';
 
 const MAX = Number.MAX_VALUE / 2;
@@ -351,3 +352,33 @@ describe('getAxisDomain', () => {
     expect(getAxisDomain([])).toBeUndefined();
   });
 });
+
+describe('getVisRatio', () => {
+  it('should return undefined for `auto` aspect', () => {
+    expect(getVisRatio('auto', [0, 1], [0, 1])).toBeUndefined();
+  });
+
+  it('should compute ratio for `equal` aspect', () => {
+    expect(getVisRatio('equal', [0, 5], [0, 5])).toBe(1);
+    expect(getVisRatio('equal', [0, 1], [0, 2])).toBe(0.5);
+    expect(getVisRatio('equal', [0, 2], [0, 1])).toBe(2);
+    expect(getVisRatio('equal', [100, 200], [10, 20])).toBe(10);
+  });
+
+  it('should compute ratio for custom aspect', () => {
+    expect(getVisRatio(1, [0, 5], [0, 5])).toBe(1);
+    expect(getVisRatio(1, [0, 1], [0, 2])).toBe(0.5);
+    expect(getVisRatio(1, [0, 2], [0, 1])).toBe(2);
+    expect(getVisRatio(1, [100, 200], [10, 20])).toBe(10);
+
+    expect(getVisRatio(0.5, [0, 5], [0, 5])).toBe(2);
+    expect(getVisRatio(0.5, [0, 1], [0, 2])).toBe(1);
+    expect(getVisRatio(0.5, [0, 2], [0, 1])).toBe(4);
+    expect(getVisRatio(0.5, [100, 200], [10, 20])).toBe(20);
+
+    expect(getVisRatio(2, [0, 5], [0, 5])).toBe(0.5);
+    expect(getVisRatio(2, [0, 1], [0, 2])).toBe(0.25);
+    expect(getVisRatio(2, [0, 2], [0, 1])).toBe(1);
+    expect(getVisRatio(2, [100, 200], [10, 20])).toBe(5);
+  });
+});