Skip to content

Commit

Permalink
fix: handle camera fixing better (#202)
Browse files Browse the repository at this point in the history
  • Loading branch information
flekschas authored Dec 11, 2024
1 parent bfc7b4b commit ddf4dd8
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.11.2

- Fix: handle camera fixing better by adding a dedicated prop called `cameraIsFixed`. Previously, the lasso end interaction would unset the camera fixing. ([#94](https://github.com/flekschas/regl-scatterplot/issues/94))

## 1.11.1

- Fix: ensure that the drawing order of points cannot be manipulated via `scatterplot.filter()` ([#197](https://github.com/flekschas/regl-scatterplot/issues/197))
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,8 @@ can be read and written via [`scatterplot.get()`](#scatterplot.get) and [`scatte
| cameraTarget | tuple | `[0, 0]` | | `true` | `false` |
| cameraDistance | float | `1` | > 0 | `true` | `false` |
| cameraRotation | float | `0` | | `true` | `false` |
| cameraView | Float32Array | `[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1`] | | `true` | `false` |
| cameraView | Float32Array | `[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]` | | `true` | `false` |
| cameraIsFixed | boolean | `false` | | `true` | `false` |
| colorBy | string | `null` | See [data encoding](#property-by) | `true` | `true` |
| sizeBy | string | `null` | See [data encoding](#property-by) | `true` | `true` |
| opacityBy | string | `null` | See [data encoding](#property-by) | `true` | `true` |
Expand Down
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export const Z_NAMES = new Set(['z', 'valueZ', 'valueA', 'value1', 'category']);
export const W_NAMES = new Set(['w', 'valueW', 'valueB', 'value2', 'value']);
export const DEFAULT_IMAGE_LOAD_TIMEOUT = 15000;
export const DEFAULT_SPATIAL_INDEX_USE_WORKER = undefined;
export const DEFAULT_CAMERA_IS_FIXED = false;

// Error messages
export const ERROR_POINTS_NOT_DRAWN = 'Points have not been drawn';
22 changes: 19 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
DEFAULT_ANNOTATION_LINE_COLOR,
DEFAULT_ANNOTATION_LINE_WIDTH,
DEFAULT_BACKGROUND_IMAGE,
DEFAULT_CAMERA_IS_FIXED,
DEFAULT_COLOR_ACTIVE,
DEFAULT_COLOR_BG,
DEFAULT_COLOR_BY,
Expand Down Expand Up @@ -287,6 +288,7 @@ const createScatterplot = (
annotationLineColor = DEFAULT_ANNOTATION_LINE_COLOR,
annotationLineWidth = DEFAULT_ANNOTATION_LINE_WIDTH,
annotationHVLineLimit = DEFAULT_ANNOTATION_HVLINE_LIMIT,
cameraIsFixed = DEFAULT_CAMERA_IS_FIXED,
} = initialProperties;

let currentWidth = width === AUTO ? 1 : width;
Expand Down Expand Up @@ -888,7 +890,7 @@ const createScatterplot = (
};

const lassoEnd = (lassoPoints, lassoPointsFlat, { merge = false } = {}) => {
camera.config({ isFixed: false });
camera.config({ isFixed: cameraIsFixed });
lassoPointsCurr = [...lassoPoints];
const pointsInLasso = findPointsInLasso(lassoPointsFlat);
select(pointsInLasso, { merge });
Expand Down Expand Up @@ -2722,7 +2724,7 @@ const createScatterplot = (
'transitionEnd',
() => {
resolve();
camera.config({ isFixed: false });
camera.config({ isFixed: cameraIsFixed });
},
1,
);
Expand Down Expand Up @@ -2921,6 +2923,11 @@ const createScatterplot = (
}
};

const setCameraIsFixed = (isFixed) => {
cameraIsFixed = Boolean(isFixed);
camera.config({ isFixed: cameraIsFixed });
};

const setLassoColor = (newLassoColor) => {
if (!newLassoColor) {
return;
Expand Down Expand Up @@ -3296,6 +3303,10 @@ const createScatterplot = (
return camera.view;
}

if (property === 'cameraIsFixed') {
return cameraIsFixed;
}

if (property === 'canvas') {
return canvas;
}
Expand Down Expand Up @@ -3616,6 +3627,10 @@ const createScatterplot = (
setCameraView(properties.cameraView);
}

if (properties.cameraIsFixed !== undefined) {
setCameraIsFixed(properties.cameraIsFixed);
}

if (properties.colorBy !== undefined) {
setColorBy(properties.colorBy);
}
Expand Down Expand Up @@ -3873,6 +3888,7 @@ const createScatterplot = (
const initCamera = () => {
if (!camera) {
camera = createDom2dCamera(canvas, {
isFixed: cameraIsFixed,
isPanInverted: [false, true],
defaultMouseDownMoveAction:
mouseMode === MOUSE_MODE_ROTATE ? 'rotate' : 'pan',
Expand Down Expand Up @@ -4083,7 +4099,7 @@ const createScatterplot = (
};

const cancelFrameListener = renderer.onFrame(() => {
// Update camera: this needs to happen on every
// Update camera: this needs to happen on every frame
isViewChanged = camera.tick();

if (!((isPointsDrawn || isAnnotationsDrawn) && (draw || isTransitioning))) {
Expand Down
1 change: 1 addition & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ interface BaseOptions {
xScale: null | Scale;
yScale: null | Scale;
pointScaleMode: PointScaleMode;
cameraIsFixed: boolean;
}

// biome-ignore lint/style/useNamingConvention: KDBush is a library name
Expand Down
2 changes: 2 additions & 0 deletions tests/constructor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import createScatterplot, {
} from '../src';

import {
DEFAULT_CAMERA_IS_FIXED,
DEFAULT_COLOR_NORMAL,
DEFAULT_COLOR_ACTIVE,
DEFAULT_COLOR_HOVER,
Expand Down Expand Up @@ -73,6 +74,7 @@ test('createScatterplot()', () => {
expect(scatterplot.get('opacityInactiveScale')).toBe(DEFAULT_OPACITY_INACTIVE_SCALE);
expect(scatterplot.get('width')).toBe(DEFAULT_WIDTH);
expect(scatterplot.get('height')).toBe(DEFAULT_HEIGHT);
expect(scatterplot.get('cameraIsFixed')).toBe(DEFAULT_CAMERA_IS_FIXED);

scatterplot.destroy();
});
Expand Down
63 changes: 62 additions & 1 deletion tests/get-set.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import '@babel/polyfill';
import { nextAnimationFrame } from '@flekschas/utils';
import { assert, expect, test } from 'vitest';

import { version } from '../package.json';
Expand Down Expand Up @@ -451,7 +452,7 @@ test(
);

expect(scatterplot.get('pointConnectionOpacityActive')).toBe(
scatterplot.get('pointConnectionOpacityActive'),
DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE,
);

scatterplot.set({
Expand Down Expand Up @@ -630,3 +631,63 @@ test(
scatterplot.destroy();
}
);

test('set({ cameraIsFixed })', async () => {
const canvas = createCanvas();
const scatterplot = createScatterplot({ canvas });

await scatterplot.draw([
[-1, 1],
[1, 1],
[0, 0],
[-1, -1],
[1, -1],
]);

canvas.dispatchEvent(new WheelEvent('wheel', { deltaY: -100 }));

await nextAnimationFrame();

console.log('1. camera distance', scatterplot.get('camera').distance[0]);

// We expect the distance to be less than one because we zoomed into the plot
// via wheeling
expect(scatterplot.get('camera').distance[0]).toBeLessThan(1);

await scatterplot.zoomToOrigin();

expect(scatterplot.get('camera').distance[0]).toBe(1);

scatterplot.set({ cameraIsFixed: true });
expect(scatterplot.get('cameraIsFixed')).toBe(true);

canvas.dispatchEvent(new WheelEvent('wheel', { deltaY: -100 }));

await nextAnimationFrame();

// We expect the distance to be one because we fixed the camera
expect(scatterplot.get('camera').distance[0]).toBe(1);

scatterplot.set({ cameraIsFixed: false });
expect(scatterplot.get('cameraIsFixed')).toBe(false);

canvas.dispatchEvent(new WheelEvent('wheel', { deltaY: -100 }));

await nextAnimationFrame();

// We expect the distance to be less than one because we unfixed the camera
expect(scatterplot.get('camera').distance[0]).toBeLessThan(1);

await scatterplot.zoomToOrigin();
expect(scatterplot.get('camera').distance[0]).toBe(1);

scatterplot.set({ cameraIsFixed: true });
await scatterplot.zoomToPoints([2]);

// Even though the camera is fixed, programmatic zooming still works. Only
// mouse wheel interactions are prevented
expect(scatterplot.get('cameraIsFixed')).toBe(true);
expect(scatterplot.get('camera').distance[0]).toBeLessThan(1);

scatterplot.destroy();
});

0 comments on commit ddf4dd8

Please sign in to comment.