Skip to content

Commit

Permalink
Added Support For Zoom Direction (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
OssamaRafique authored Apr 7, 2024
1 parent e83c85c commit b0249bf
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 112 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ setViewOptions({
});
```

### Zoom Control Direction

You can now specify to use natural scrolling or inverted scrolling for zooming in and out using the `setViewOptions` function. Default value is `true`.

```javascript
setViewOptions({
useNaturalScrolling: false,
});
```

# Specifications

Documentation for specifications can be found in [docs/specification_doc.md](https://github.com/epiviz/epiviz.gl/blob/main/docs/specification_doc.md). Documentation for the specifications can be generated with [json-schema-for-humans](https://pypi.org/project/json-schema-for-humans/):
Expand Down
189 changes: 102 additions & 87 deletions app/index.html
Original file line number Diff line number Diff line change
@@ -1,93 +1,108 @@
<html>
<head>
<title>epiviz.gl demo</title>
<meta name="title" content="Epiviz.gl demo" />
<meta
name="description"
content="A demo of an interactive point visualization using WebGL"
/>
<link rel="stylesheet" href="./styles/index.css" />
<link rel="icon" href="./assets/favicon.ico" type="image/x-icon" />
<script type="module" src="./scripts/index.js"></script>
</head>

<head>
<title>epiviz.gl demo</title>
<meta name="title" content="Epiviz.gl demo" />
<meta name="description" content="A demo of an interactive point visualization using WebGL" />
<link rel="stylesheet" href="./styles/index.css" />
<link rel="icon" href="./assets/favicon.ico" type="image/x-icon" />
<script type="module" src="./scripts/index.js"></script>
</head>

<body>
<main>
<div class="toolbar">
<div class="specification-select">
<label for="specification-select">Load Spec:</label>
<select name="specification-select" id="specification-select">
<option value="line-plot">Line Plot</option>
<option value="double-line-plot">Double Line Plot</option>
<option value="area-chart">Area Chart</option>
<option value="stacked-area-chart">Stacked Area Chart</option>
<option value="tick-chart">Tick Chart</option>
<option value="inline-data">Inline Data</option>
<option value="data-defined-channels">Data Defined Channels</option>
<option value="double-inline-data">Double Inline Data</option>
<option value="scatter-grid">Grid Scatter Plot</option>
<option value="scatter-grid-margins">
Grid Scatter Plot With Margins
</option>
<option value="tiny-scatter">Tiny Scatter Plot</option>
<option value="heatmap">Heatmap</option>
<option value="signed-bar-chart">Signed Bar Chart</option>
<option value="vertical-signed-bar-chart">
Vertical Signed Bar Chart
</option>
<option value="all-tracks">All Tracks</option>
<option value="arc-track">Arc Track</option>
<option value="box-track">Box Track</option>
<option value="line-track">Line Track</option>
<option value="tsne-100th">t-SNE Dataset (1/100)</option>
<option value="tsne-10th">t-SNE Dataset (1/10)</option>
<option value="tsne">t-SNE Dataset</option>
<option value="matrix">Large Matrix</option>
</select>
</div>
<div class="controls">
Control modes:
<span>
<img src="./assets/pan_tool_black_24dp.svg" alt="pan tool" />
Pan Tool </span>
<span>
<img src="./assets/highlight_alt_black_24dp.svg" alt="box select" />
Selection (Box)
</span>
<span>
<img src="./assets/gesture_black_24dp.svg" alt="lasso select" />
Selection (Lasso)
</span>
<!-- <img src="./assets/zoom_in_black_24dp.svg" alt="zoom in" /> -->
<!-- <img src="./assets/touch_app_black_24dp.svg" alt="tooltip examine" /> -->
</div>
<body>
<main>
<div class="toolbar">
<div class="specification-select">
<label for="specification-select">Load Spec:</label>
<select name="specification-select" id="specification-select">
<option value="line-plot">Line Plot</option>
<option value="double-line-plot">Double Line Plot</option>
<option value="area-chart">Area Chart</option>
<option value="stacked-area-chart">Stacked Area Chart</option>
<option value="tick-chart">Tick Chart</option>
<option value="inline-data">Inline Data</option>
<option value="data-defined-channels">Data Defined Channels</option>
<option value="double-inline-data">Double Inline Data</option>
<option value="scatter-grid">Grid Scatter Plot</option>
<option value="scatter-grid-margins">
Grid Scatter Plot With Margins
</option>
<option value="tiny-scatter">Tiny Scatter Plot</option>
<option value="heatmap">Heatmap</option>
<option value="signed-bar-chart">Signed Bar Chart</option>
<option value="vertical-signed-bar-chart">
Vertical Signed Bar Chart
</option>
<option value="all-tracks">All Tracks</option>
<option value="arc-track">Arc Track</option>
<option value="box-track">Box Track</option>
<option value="line-track">Line Track</option>
<option value="tsne-100th">t-SNE Dataset (1/100)</option>
<option value="tsne-10th">t-SNE Dataset (1/10)</option>
<option value="tsne">t-SNE Dataset</option>
<option value="matrix">Large Matrix</option>
</select>
</div>
<div class="controls">
Control modes:
<span>
<img src="./assets/pan_tool_black_24dp.svg" alt="pan tool" />
Pan Tool
</span>
<span>
<img src="./assets/highlight_alt_black_24dp.svg" alt="box select" />
Selection (Box)
</span>
<span>
<img src="./assets/gesture_black_24dp.svg" alt="lasso select" />
Selection (Lasso)
</span>
<!-- <img src="./assets/zoom_in_black_24dp.svg" alt="zoom in" /> -->
<!-- <img src="./assets/touch_app_black_24dp.svg" alt="tooltip examine" /> -->
</div>

<div class="scroll-state">
Lock pan/zoom along an axis ?
<span>
<label for="lock-x">Lock X</label>
<input type="checkbox" id="lock-x" name="lock-x" />
</span>
<span>
<label for="lock-x">Lock Y</label>
<input type="checkbox" id="lock-y" name="lock-y" />
</span>
<div class="scroll-state">
Lock pan/zoom along an axis ?
<span>
<label for="lock-x">Lock X</label>
<input type="checkbox" id="lock-x" name="lock-x" />
</span>
<span>
<label for="lock-x">Lock Y</label>
<input type="checkbox" id="lock-y" name="lock-y" />
</span>
<span>
<label for="use-natural-scroll">Use Natural Scroll</label>
<input
type="checkbox"
id="use-natural-scroll"
name="use-natural-scroll"
/>
</span>
</div>
</div>
</div>
<div class="panes">
<div class="json-editor">
<div>
<label for="specification-editor">Visualization Specification</label>
<button id="refresh-specification">RUN</button>
<div class="panes">
<div class="json-editor">
<div>
<label for="specification-editor"
>Visualization Specification</label
>
<button id="refresh-specification">RUN</button>
</div>
<textarea
id="specification-editor"
name="specification-editor"
></textarea>
</div>
<textarea id="specification-editor" name="specification-editor"></textarea>
<div class="content"></div>
</div>
<div class="content"></div>
</div>
</main>
<footer>
<a class="github" href="https://github.com/epiviz/epiviz.gl">
See on GitHub
</a>
</footer>
</body>

</html>
</main>
<footer>
<a class="github" href="https://github.com/epiviz/epiviz.gl">
See on GitHub
</a>
</footer>
</body>
</html>
2 changes: 1 addition & 1 deletion app/scripts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class App {

let selem = document.getElementById("specification-select");
selem.value = "tsne-10th";
selem.dispatchEvent(new Event('change'));
selem.dispatchEvent(new Event("change"));

document.getElementById("refresh-specification").click();
}
Expand Down
15 changes: 11 additions & 4 deletions app/scripts/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const controlsSlice = createSlice({
specification: csv10,
lockedX: false,
lockedY: false,
useNaturalScrolling: false,
},
reducers: {
setSpecification(state, action) {
Expand All @@ -19,10 +20,16 @@ const controlsSlice = createSlice({
},

setScroll(state, action) {
if (action.payload.axis === "x") {
state.lockedX = action.payload.checked;
} else if (action.payload.axis === "y") {
state.lockedY = action.payload.checked;
if (action.payload.axis) {
if (action.payload.axis === "x") {
state.lockedX = action.payload.checked;
} else if (action.payload.axis === "y") {
state.lockedY = action.payload.checked;
}
} else {
for (const key in action.payload) {
state[key] = action.payload[key];
}
}
},
},
Expand Down
5 changes: 5 additions & 0 deletions app/scripts/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ class Toolbar {
document.getElementById("lock-y").addEventListener("change", (event) => {
this.dispatch(setScroll({ axis: "y", checked: event.target.checked }));
});
document
.getElementById("use-natural-scroll")
.addEventListener("change", (event) => {
this.dispatch(setScroll({ useNaturalScrolling: event.target.checked }));
});

document.getElementById("specification-select").value = this.specification;
this.dispatch(setSpecification(exampleMap.get(this.specification)));
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "epiviz.gl",
"version": "1.0.17",
"version": "1.0.18",
"repository": "https://github.com/epiviz/epiviz.gl",
"homepage": "https://github.com/epiviz/epiviz.gl",
"author": {
Expand All @@ -12,6 +12,10 @@
{
"name": "Sam Rosen",
"email": "[email protected]"
},
{
"name": "Ossama Rafique",
"email": "[email protected]"
}
],
"bugs": "https://github.com/epiviz/epiviz.gl/issues",
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import commonjs from "@rollup/plugin-commonjs";
import pkg from "./package.json";
import json from "@rollup/plugin-json";
import OMT from "@surma/rollup-plugin-off-main-thread";
import nodePolyfills from "rollup-plugin-node-polyfills"; // <-- import here
import nodePolyfills from "rollup-plugin-node-polyfills";

export default {
input: "src/index.js",
Expand Down
26 changes: 18 additions & 8 deletions src/epiviz.gl/mouse-reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class MouseReader {
);
this.throttledUpdateSVG = throttleWithRAF(this._updateSVG.bind(this));
this.uniDirectionalSelectionEnabled = true;
this.useNaturalScrolling = false;
}

/**
Expand Down Expand Up @@ -299,7 +300,9 @@ class MouseReader {
let previousY = null;
if (!this.lockedX) {
previousX = [...this.currentXRange]; // ... to avoid aliasing
const t = -event.wheelDelta / 1000;
const t = this.useNaturalScrolling
? event.wheelDelta / 1000
: -event.wheelDelta / 1000; // Invert based on scrolling preference
const inDataSpace = this._calculateViewportSpot(
...getLayerXandYFromEvent(event)
);
Expand All @@ -315,7 +318,9 @@ class MouseReader {

if (!this.lockedY) {
previousY = [...this.currentYRange];
const t = -event.wheelDelta / 1000;
const t = this.useNaturalScrolling
? event.wheelDelta / 1000
: -event.wheelDelta / 1000; // Invert based on scrolling preference
const inDataSpace = this._calculateViewportSpot(
...getLayerXandYFromEvent(event)
);
Expand Down Expand Up @@ -349,12 +354,17 @@ class MouseReader {
}
}

this.handler.dispatchEvent(event.wheelDelta < 0 ? "zoomIn" : "zoomOut", {
viewport: this.getViewport(),
zoomLevel: calculateZoomLevel(this.getViewport()),
type: this.tool,
event: cloneMouseEvent(event),
});
this.handler.dispatchEvent(
(this.useNaturalScrolling ? event.wheelDelta < 0 : event.wheelDelta > 0)
? "zoomIn"
: "zoomOut",
{
viewport: this.getViewport(),
zoomLevel: calculateZoomLevel(this.getViewport()),
type: this.tool,
event: cloneMouseEvent(event),
}
);

this.handler.sendDrawerState(this.getViewport());
this.throttledUpdateSVG();
Expand Down
1 change: 1 addition & 0 deletions src/epiviz.gl/webgl-vis.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class WebGLVis {
"currentYRange",
"uniDirectionalSelectionEnabled",
"maxZoomLevel",
"useNaturalScrolling",
]);
}

Expand Down
10 changes: 0 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4238,11 +4238,6 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==

process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==

[email protected]:
version "1.0.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
Expand All @@ -4266,11 +4261,6 @@ [email protected]:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=

punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==

punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
Expand Down

0 comments on commit b0249bf

Please sign in to comment.