From 165ed7d9e87935b205d54c710332038cdafd39ec Mon Sep 17 00:00:00 2001 From: Ossama Rafique Date: Mon, 7 Aug 2023 11:58:03 -0700 Subject: [PATCH] Added option to set max zoom level (#71) * Added option to set max zoom level * Incorporated PR feedback * Added documentation & bumped up version --- README.md | 10 ++++++++++ package.json | 2 +- src/epiviz.gl/mouse-reader.js | 33 +++++++++++++++++++++++++-------- src/epiviz.gl/utilities.js | 29 +++++++++++++++++++++++++---- src/epiviz.gl/webgl-vis.js | 2 ++ 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2cfae7c..9a354c0 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,16 @@ plot.setViewOptions({ By setting the argument to true, the unidirectional selection will be enabled. Setting it to false will disable this feature. +### Graph Zoom Control + +The enhanced graph visualization tool now offers refined zoom controls, ensuring a precise and adaptable data representation. You can now set max zoom level allowed in the graph using the `setViewOptions` function. + +```javascript +setViewOptions({ + maxZoomLevel: 0, +}); +``` + # 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/): diff --git a/package.json b/package.json index c2c69ed..9e645da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "epiviz.gl", - "version": "1.0.13", + "version": "1.0.14", "repository": "https://github.com/epiviz/epiviz.gl", "homepage": "https://github.com/epiviz/epiviz.gl", "author": { diff --git a/src/epiviz.gl/mouse-reader.js b/src/epiviz.gl/mouse-reader.js index 2f49900..3ba4ec2 100644 --- a/src/epiviz.gl/mouse-reader.js +++ b/src/epiviz.gl/mouse-reader.js @@ -4,6 +4,7 @@ import { getDimAndMarginStyleForSpecification, cloneMouseEvent, getPointsBySelectMode, + calculateZoomLevel, } from "./utilities"; import SVGInteractor from "./svg-interactor"; @@ -289,8 +290,11 @@ class MouseReader { */ _onWheel(event) { event.preventDefault(); + + let previousX = null; + let previousY = null; if (!this.lockedX) { - const previousX = [...this.currentXRange]; // ... to avoid aliasing + previousX = [...this.currentXRange]; // ... to avoid aliasing const t = -event.wheelDelta / 1000; const inDataSpace = this._calculateViewportSpot( ...getLayerXandYFromEvent(event) @@ -303,15 +307,10 @@ class MouseReader { this.currentXRange[0] = Math.max(this.currentXRange[0], this.minX); this.currentXRange[1] = Math.min(this.currentXRange[1], this.maxX); - - if (!this._validateXRange()) { - // Zoom in limit - this.currentXRange = previousX; - } } if (!this.lockedY) { - const previousY = [...this.currentYRange]; + previousY = [...this.currentYRange]; const t = -event.wheelDelta / 1000; const inDataSpace = this._calculateViewportSpot( ...getLayerXandYFromEvent(event) @@ -323,14 +322,32 @@ class MouseReader { t * inDataSpace[1] + (1 - t) * this.currentYRange[1]; this.currentYRange[0] = Math.max(this.currentYRange[0], this.minY); this.currentYRange[1] = Math.min(this.currentYRange[1], this.maxY); + } - if (!this._validateYRange()) { + if (!this.lockedX || !this.lockedY) { + const { xZoomLevel, yZoomLevel } = calculateZoomLevel(this.getViewport()); + if ( + !this.lockedX && + (!this._validateXRange() || + (this.maxZoomLevel && this.maxZoomLevel < xZoomLevel)) + ) { + // Zoom in limit + this.currentXRange = previousX; + } + + if ( + !this.lockedY && + (!this._validateYRange() || + (this.maxZoomLevel && this.maxZoomLevel < yZoomLevel)) + ) { // Zoom in limit this.currentYRange = previousY; } } + this.handler.dispatchEvent(event.wheelDelta < 0 ? "zoomIn" : "zoomOut", { viewport: this.getViewport(), + zoomLevel: calculateZoomLevel(this.getViewport()), type: this.tool, event: cloneMouseEvent(event), }); diff --git a/src/epiviz.gl/utilities.js b/src/epiviz.gl/utilities.js index c388e29..4e73960 100644 --- a/src/epiviz.gl/utilities.js +++ b/src/epiviz.gl/utilities.js @@ -296,6 +296,26 @@ const cloneMouseEvent = (e) => { }; }; +const calculateZoomLevel = (viewport) => { + const { minX, minY, maxX, maxY, xRange, yRange } = viewport; + // Calculate the full range for content + const fullXRange = maxX - minX; + const fullYRange = maxY - minY; + + // Calculate the range of the visible viewport + const viewportWidth = xRange[1] - xRange[0]; + const viewportHeight = yRange[1] - yRange[0]; + + // Determine the zoom levels for X and Y + const xZoomLevel = fullXRange / viewportWidth; + const yZoomLevel = fullYRange / viewportHeight; + + return { + xZoomLevel, + yZoomLevel, + }; +}; + const getPointsBySelectMode = (selectMode, originalPoints, xRange, yRange) => { const points = [...originalPoints]; switch (selectMode) { @@ -313,15 +333,16 @@ const getPointsBySelectMode = (selectMode, originalPoints, xRange, yRange) => { export { cloneMouseEvent, - scale, - rgbToHex, - rgbStringToHex, + colorSpecifierToHex, + calculateZoomLevel, getPointsBySelectMode, getViewportForSpecification, - colorSpecifierToHex, getScaleForSpecification, getDimAndMarginStyleForSpecification, getQuadraticBezierCurveForPoints, + rgbToHex, + rgbStringToHex, + scale, DEFAULT_WIDTH, DEFAULT_HEIGHT, }; diff --git a/src/epiviz.gl/webgl-vis.js b/src/epiviz.gl/webgl-vis.js index e3b66f7..504dab3 100644 --- a/src/epiviz.gl/webgl-vis.js +++ b/src/epiviz.gl/webgl-vis.js @@ -32,6 +32,7 @@ class WebGLVis { "currentXRange", "currentYRange", "uniDirectionalSelectionEnabled", + "maxZoomLevel", ]); } @@ -143,6 +144,7 @@ class WebGLVis { * currentYRange: [y1, y2] (Numbers that should be within the viewport minY and maxY) * uniDirectionalSelectionEnabled: boolean * tool: one of ["pan", "box", "lasso"] + * maxZoomLevel: Number * * @param {Object} options with keys under WebGLVis.POSSIBLE_MOUSE_READER_OPTIONS */