mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-24 10:48:11 +08:00
TS Revert (1) (#2402)
* revert all commits to before Typescript migration * update compat workflow to match latest deps (#2335) * update compat workflow to match latest deps * attempt to debug * attempt to debug * remove debugging code * typo * update deps to match desktop (#2340) * fix: don't run lint with `--fix` on push tests (#2273) * fix: don't run lint with `--fix` on push tests * npx Co-authored-by: maniarathi <mani.arathi@gmail.com> Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com> * rename X_approx_distribution to X_approximate_distribution (#2337) * Correctly handle non-finite numbers in heuristic determination of X distribution (#2342) * handle non-finites explicitly * improve and test edge case handling for distribution estimation * revert debugging changes * code readability * clean up type inferencing (#2332) * unit tests for 64 bit conversion * clean up type handling * type inference tests * more type inference fixes * use schema to determine user intent for data typing * stop using deprecated API * fbs type encoding test * add missing test * add more tests * correctly infer X type for CXG adaptor * lint * fix typo * ts migration * cleanup from PR review * lint * PR review changes * remove unused packages from client (#2359) * remove unused packages from client * add missing peer dep * fix: disable FE auth testing on compatibility tests (#2377) * update: release process (#2277) Co-authored-by: maniarathi <mani.arathi@gmail.com> * fix: remove spaces in param setup (#2380) * delete deploy workflow (#2396) * undo reformatting which now does not pass lint * fix snapshots which changed due to npm dep changes * add missing quoting to snapshot * another snapshot typo fix * TS Revert (2) - replay PR #2347 and #2354 (#2403) * replay edits from PR 2347 * TS Revert (3) - replay edits in PR #2327 (#2404) * replay edits in PR 2327 * TS Revert (4) - replay PR #2355 (#2405) * replay edits in PR 2355 * add additional babel config * reformat with new prettier config Co-authored-by: Severiano Badajoz <sbadajoz@chanzuckerberg.com> Co-authored-by: maniarathi <mani.arathi@gmail.com> Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com>
This commit is contained in:
co-authored by
maniarathi
Madison Dunitz
Severiano Badajoz
parent
295590a7c6
commit
eaae6df5e3
@@ -0,0 +1,180 @@
|
||||
import { vec2, mat3 } from "gl-matrix";
|
||||
|
||||
const EPSILON = 0.000001;
|
||||
|
||||
const scaleSpeed = 0.5;
|
||||
const scaleMax = 3.0;
|
||||
const scaleMin = 0.5;
|
||||
const panBound = 0.8;
|
||||
|
||||
// private
|
||||
const scratch0 = new Float32Array(16);
|
||||
const scratch1 = new Float32Array(16);
|
||||
|
||||
function clamp(val, rng) {
|
||||
return Math.max(Math.min(val, rng[1]), rng[0]);
|
||||
}
|
||||
|
||||
class Camera {
|
||||
constructor(canvas) {
|
||||
this.prevEvent = {
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
type: 0,
|
||||
};
|
||||
this.canvas = canvas;
|
||||
this.viewMatrix = mat3.create();
|
||||
this.viewMatrixInv = mat3.create();
|
||||
}
|
||||
|
||||
view() {
|
||||
return this.viewMatrix;
|
||||
}
|
||||
|
||||
invView() {
|
||||
return this.viewMatrixInv;
|
||||
}
|
||||
|
||||
distance() {
|
||||
return this.viewMatrix[0];
|
||||
}
|
||||
|
||||
pan(dx, dy) {
|
||||
const m = this.viewMatrix;
|
||||
const dyRange = [
|
||||
-panBound - (m[7] + 1) / m[4],
|
||||
panBound - (m[7] - 1) / m[4],
|
||||
];
|
||||
const dxRange = [
|
||||
-panBound - (m[6] + 1) / m[0],
|
||||
panBound - (m[6] - 1) / m[0],
|
||||
];
|
||||
|
||||
const dxClamped = clamp(dx, dxRange);
|
||||
const dyClamped = clamp(dy, dyRange);
|
||||
if (Math.abs(dxClamped) <= EPSILON && Math.abs(dyClamped) <= EPSILON)
|
||||
return;
|
||||
|
||||
mat3.translate(m, m, [dxClamped, dyClamped]);
|
||||
mat3.invert(this.viewMatrixInv, m);
|
||||
}
|
||||
|
||||
zoomAt(d, x = 0, y = 0) {
|
||||
/*
|
||||
Camera zoom at [x,y]
|
||||
*/
|
||||
const m = this.viewMatrix;
|
||||
const bounds = [-panBound, panBound];
|
||||
x = clamp(x, bounds);
|
||||
y = clamp(y, bounds);
|
||||
|
||||
const dClamped = clamp(d * m[0], [scaleMin, scaleMax]) / m[0];
|
||||
if (Math.abs(1 - dClamped) <= EPSILON) return; // noop request
|
||||
|
||||
mat3.translate(m, m, [x, y]);
|
||||
mat3.scale(m, m, [dClamped, dClamped]);
|
||||
mat3.translate(m, m, [-x, -y]);
|
||||
|
||||
mat3.invert(this.viewMatrixInv, m);
|
||||
}
|
||||
|
||||
/*
|
||||
Event handling
|
||||
*/
|
||||
|
||||
flush(e) {
|
||||
this.prevEvent.type = e.type;
|
||||
this.prevEvent.clientX = e.clientX;
|
||||
this.prevEvent.clientY = e.clientY;
|
||||
}
|
||||
|
||||
localPosition(target, canvasX, canvasY, projectionInvTF) {
|
||||
/*
|
||||
Convert mouse position to local
|
||||
*/
|
||||
const { height, width } = target;
|
||||
const targetRect = target.getBoundingClientRect();
|
||||
canvasX -= targetRect.left;
|
||||
canvasY -= targetRect.top;
|
||||
|
||||
const pos = vec2.fromValues(
|
||||
2 * (canvasX / width) - 1,
|
||||
-2 * (canvasY / height) + 1
|
||||
);
|
||||
if (projectionInvTF) {
|
||||
vec2.transformMat3(pos, pos, projectionInvTF);
|
||||
}
|
||||
vec2.transformMat3(pos, pos, this.invView());
|
||||
return pos;
|
||||
}
|
||||
|
||||
mousePan(e, projectionTF) {
|
||||
const projectionInvTF = mat3.invert(scratch0, projectionTF);
|
||||
const pos = this.localPosition(
|
||||
this.canvas,
|
||||
e.clientX,
|
||||
e.clientY,
|
||||
projectionInvTF
|
||||
);
|
||||
const prev = this.localPosition(
|
||||
this.canvas,
|
||||
this.prevEvent.clientX,
|
||||
this.prevEvent.clientY,
|
||||
projectionInvTF
|
||||
);
|
||||
|
||||
const delta = vec2.sub(scratch1, pos, prev);
|
||||
this.pan(delta[0], delta[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
wheelZoom(e, projectionTF) {
|
||||
const { height } = this.canvas;
|
||||
const { deltaY, deltaMode, clientX, clientY } = e;
|
||||
const scale = scaleSpeed * (deltaMode === 1 ? 12 : 1) * (deltaY || 0);
|
||||
|
||||
const projectionInvTF = mat3.invert(scratch0, projectionTF);
|
||||
const pos = this.localPosition(
|
||||
this.canvas,
|
||||
clientX,
|
||||
clientY,
|
||||
projectionInvTF
|
||||
);
|
||||
this.zoomAt(1 / Math.exp(scale / height), pos[0], pos[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
handleEvent(e, projectionTF) {
|
||||
/*
|
||||
process the event, and return true if camera view changed
|
||||
*/
|
||||
let viewChanged = false;
|
||||
switch (e.type) {
|
||||
case "mousemove": {
|
||||
/* eslint-disable-next-line no-bitwise --- MouseEvent.buttons exposes a bitmask, best acted on with bitops */
|
||||
if (e.buttons & 0x1) {
|
||||
viewChanged = this.mousePan(e, projectionTF);
|
||||
}
|
||||
this.flush(e);
|
||||
break;
|
||||
}
|
||||
|
||||
case "wheel": {
|
||||
viewChanged = this.wheelZoom(e, projectionTF);
|
||||
this.flush(e);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// noop
|
||||
break;
|
||||
}
|
||||
return viewChanged;
|
||||
}
|
||||
}
|
||||
|
||||
function attachCamera(canvas) {
|
||||
return new Camera(canvas);
|
||||
}
|
||||
|
||||
export default attachCamera;
|
||||
Reference in New Issue
Block a user