From 3df05482ea472ee8463cbd396f55bc565731b23d Mon Sep 17 00:00:00 2001 From: Timmy Willison <4timmywil@gmail.com> Date: Mon, 18 Nov 2019 15:34:17 -0500 Subject: [PATCH] fix(zoom): need the before and after dimensions to constrain Fixes gh-426 --- README.md | 88 +++++++++++++++++++++--------------------- demo/global-panzoom.ts | 8 ++++ demo/index.tsx | 8 ++-- src/panzoom.ts | 49 +++++++++++++---------- src/types.ts | 6 ++- webpack.config.js | 3 +- 6 files changed, 94 insertions(+), 68 deletions(-) create mode 100644 demo/global-panzoom.ts diff --git a/README.md b/README.md index 3bdf3b37..f449a662 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Alternatively, add a reference to the element to the `exclude` option, or call ` ▸ **Panzoom**(`elem`: HTMLElement | SVGElement, `options?`: Omit‹[PanzoomOptions](#PanzoomOptions), "force"›): _[PanzoomObject](#PanzoomObject)_ -_Defined in [panzoom.ts:45](https://github.com/timmywil/panzoom/blob/5a075a0/src/panzoom.ts#L45)_ +_Defined in [panzoom.ts:47](https://github.com/timmywil/panzoom/blob/761a0ec/src/panzoom.ts#L47)_ **Parameters:** @@ -138,7 +138,7 @@ Includes `MiscOptions`, `PanOptions`, and `ZoomOptions` • **animate**? : _boolean_ (Default: **false**) -_Defined in [types.ts:13](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L13)_ +_Defined in [types.ts:13](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L13)_ Whether to animate transitions @@ -148,7 +148,7 @@ Whether to animate transitions • **duration**? : _number_ (Default: **200**) -_Defined in [types.ts:15](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L15)_ +_Defined in [types.ts:15](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L15)_ Duration of the transition (ms) @@ -158,7 +158,7 @@ Duration of the transition (ms) • **easing**? : _string_ (Default: **"ease-in-out"**) -_Defined in [types.ts:17](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L17)_ +_Defined in [types.ts:17](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L17)_ CSS Easing used for transitions @@ -168,7 +168,7 @@ CSS Easing used for transitions • **exclude**? : _Element[]_ -_Defined in [types.ts:23](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L23)_ +_Defined in [types.ts:23](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L23)_ Add elements to this array that should be excluded from Panzoom handling. @@ -180,7 +180,7 @@ e.g. links and buttons that should not propagate the click event. • **excludeClass**? : _string_ (Default: **"panzoom-exclude"**) -_Defined in [types.ts:29](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L29)_ +_Defined in [types.ts:29](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L29)_ Add this class to any element within the Panzoom element that you want to exclude from Panzoom handling. @@ -192,7 +192,7 @@ e.g. links and buttons that should not propagate the click event. • **force**? : _boolean_ -_Defined in [types.ts:45](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L45)_ +_Defined in [types.ts:45](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L45)_ `force` should be used sparingly to temporarily override and ignore options such as disablePan, @@ -214,7 +214,7 @@ panzoom.zoom(1, { force: true }) • **handleStartEvent**? : _function_ -_Defined in [types.ts:69](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L69)_ +_Defined in [types.ts:69](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L69)_ On the first pointer event, when panning starts, the default Panzoom behavior is to call @@ -254,7 +254,7 @@ Panzoom(elem, { • **origin**? : _string_ -_Defined in [types.ts:83](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L83)_ +_Defined in [types.ts:83](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L83)_ **Change this at your own risk.** The `transform-origin` is the origin from which transforms are applied. @@ -274,7 +274,7 @@ And again, changing this for SVG in IE doesn't work at all. • **setTransform**? : _setTransform_ -_Defined in [types.ts:101](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L101)_ +_Defined in [types.ts:101](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L101)_ Override the transform setter. This is exposed mostly so the user could @@ -298,7 +298,7 @@ const panzoom = Panzoom(elem, { • **silent**? : _boolean_ -_Defined in [types.ts:103](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L103)_ +_Defined in [types.ts:103](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L103)_ Silence all events @@ -308,7 +308,7 @@ Silence all events • **startScale**? : _number_ (Default: **1**) -_Defined in [types.ts:109](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L109)_ +_Defined in [types.ts:109](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L109)_ Scale used to set the beginning transform @@ -318,7 +318,7 @@ Scale used to set the beginning transform • **startX**? : _number_ (Default: **0**) -_Defined in [types.ts:105](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L105)_ +_Defined in [types.ts:105](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L105)_ X Value used to set the beginning transform @@ -328,7 +328,7 @@ X Value used to set the beginning transform • **startY**? : _number_ (Default: **0**) -_Defined in [types.ts:107](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L107)_ +_Defined in [types.ts:107](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L107)_ Y Value used to set the beginning transform @@ -342,7 +342,7 @@ Includes `MiscOptions` • **contain**? : _"inside" | "outside"_ -_Defined in [types.ts:126](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L126)_ +_Defined in [types.ts:126](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L126)_ Contain the panzoom element either inside or outside the parent. @@ -360,7 +360,7 @@ empty space around the element will be shown. • **cursor**? : _string_ (Default: **"move"**) -_Defined in [types.ts:128](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L128)_ +_Defined in [types.ts:128](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L128)_ The cursor style to set on the panzoom element @@ -370,9 +370,11 @@ The cursor style to set on the panzoom element • **disablePan**? : _boolean_ (Default: **false**) -_Defined in [types.ts:130](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L130)_ +_Defined in [types.ts:134](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L134)_ -Disable panning functionality. Note: disablePan also disables focal point zooming +Disable panning functionality. +Note: disablePan does not affect focal point zooming or the constrain option. +The element will still pan accordingly. --- @@ -380,7 +382,7 @@ Disable panning functionality. Note: disablePan also disables focal point zoomin • **disableXAxis**? : _boolean_ (Default: **false**) -_Defined in [types.ts:132](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L132)_ +_Defined in [types.ts:136](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L136)_ Pan only on the Y axis @@ -390,7 +392,7 @@ Pan only on the Y axis • **disableYAxis**? : _boolean_ (Default: **false**) -_Defined in [types.ts:134](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L134)_ +_Defined in [types.ts:138](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L138)_ Pan only on the X axis @@ -400,7 +402,7 @@ Pan only on the X axis • **panOnlyWhenZoomed**? : _boolean_ (Default: **false**) -_Defined in [types.ts:138](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L138)_ +_Defined in [types.ts:142](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L142)_ Disable panning while the scale is equal to the starting value @@ -410,7 +412,7 @@ Disable panning while the scale is equal to the starting value • **relative**? : _boolean_ (Default: **false**) -_Defined in [types.ts:136](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L136)_ +_Defined in [types.ts:140](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L140)_ When passing x and y values to .pan(), treat the values as relative to their current values @@ -424,7 +426,7 @@ Includes `MiscOptions` • **disableZoom**? : _boolean_ (Default: **false**) -_Defined in [types.ts:143](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L143)_ +_Defined in [types.ts:147](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L147)_ Disable zooming functionality @@ -434,7 +436,7 @@ Disable zooming functionality • **focal**? : _object_ -_Defined in [types.ts:150](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L150)_ +_Defined in [types.ts:154](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L154)_ Zoom to the given point on the panzoom element. This point is expected to be relative to @@ -453,7 +455,7 @@ to the parent dimensions. • **maxScale**? : _number_ (Default: **4**) -_Defined in [types.ts:154](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L154)_ +_Defined in [types.ts:158](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L158)_ The maximum scale when zooming @@ -463,7 +465,7 @@ The maximum scale when zooming • **minScale**? : _number_ (Default: **0.125**) -_Defined in [types.ts:152](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L152)_ +_Defined in [types.ts:156](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L156)_ The minimum scale when zooming @@ -473,7 +475,7 @@ The minimum scale when zooming • **step**? : _number_ (Default: **0.3**) -_Defined in [types.ts:156](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L156)_ +_Defined in [types.ts:160](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L160)_ The step affects zoom calculation when zooming with a mouse wheel, when pinch zooming, or when using zoomIn/zoomOut @@ -487,7 +489,7 @@ These methods are available after initializing Panzoom • **destroy**: _function_ -_Defined in [types.ts:171](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L171)_ +_Defined in [types.ts:175](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L175)_ Remove all event listeners bind to the the Panzoom element @@ -501,7 +503,7 @@ Remove all event listeners bind to the the Panzoom element • **getOptions**: _function_ -_Defined in [types.ts:177](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L177)_ +_Defined in [types.ts:181](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L181)_ Returns a _copy_ of the current options object @@ -515,7 +517,7 @@ Returns a _copy_ of the current options object • **getPan**: _function_ -_Defined in [types.ts:173](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L173)_ +_Defined in [types.ts:177](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L177)_ Get the current x/y translation @@ -533,7 +535,7 @@ Get the current x/y translation • **getScale**: _function_ -_Defined in [types.ts:175](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L175)_ +_Defined in [types.ts:179](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L179)_ Get the current scale @@ -547,7 +549,7 @@ Get the current scale • **pan**: _function_ -_Defined in [types.ts:188](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L188)_ +_Defined in [types.ts:192](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L192)_ Pan the Panzoom element to the given x and y coordinates @@ -576,7 +578,7 @@ panzoom.pan(10, 10, { relative: true }) • **reset**: _function_ -_Defined in [types.ts:199](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L199)_ +_Defined in [types.ts:203](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L203)_ Reset the pan and zoom to startX, startY, and startScale. Animates by default, ignoring the global option. @@ -603,7 +605,7 @@ panzoom.reset({ animate: false }) • **setOptions**: _function_ -_Defined in [types.ts:201](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L201)_ +_Defined in [types.ts:205](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L205)_ Change options for the Panzoom instance @@ -623,7 +625,7 @@ Change options for the Panzoom instance • **setStyle**: _function_ -_Defined in [types.ts:203](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L203)_ +_Defined in [types.ts:207](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L207)_ A convenience method for setting prefixed styles on the Panzoom element @@ -644,7 +646,7 @@ A convenience method for setting prefixed styles on the Panzoom element • **zoom**: _function_ -_Defined in [types.ts:212](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L212)_ +_Defined in [types.ts:216](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L216)_ Zoom the Panzoom element to the given scale @@ -670,7 +672,7 @@ panzoom.zoom(2.2, { animate: true }) • **zoomIn**: _function_ -_Defined in [types.ts:223](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L223)_ +_Defined in [types.ts:227](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L227)_ Zoom in using the predetermined increment set in options. Animates by default, ignoring the global option. @@ -697,7 +699,7 @@ panzoom.zoomIn({ animate: false }) • **zoomOut**: _function_ -_Defined in [types.ts:234](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L234)_ +_Defined in [types.ts:238](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L238)_ Zoom out using the predetermined increment set in options. Animates by default, ignoring the global option. @@ -724,7 +726,7 @@ panzoom.zoomOut({ animate: false }) • **zoomToPoint**: _function_ -_Defined in [types.ts:245](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L245)_ +_Defined in [types.ts:249](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L249)_ Zoom the Panzoom element to a focal point using the given pointer/touch/mouse event or constructed point. @@ -758,7 +760,7 @@ panzoom.zoomToPoint(1.2, pointerEvent) • **zoomWithWheel**: _function_ -_Defined in [types.ts:274](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L274)_ +_Defined in [types.ts:278](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L278)_ Zoom the Panzoom element to a focal point using the given WheelEvent @@ -802,7 +804,7 @@ elem.parentElement.addEventListener('wheel', function(event) { • **scale**: _number_ -_Defined in [types.ts:166](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L166)_ +_Defined in [types.ts:170](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L170)_ --- @@ -810,7 +812,7 @@ _Defined in [types.ts:166](https://github.com/timmywil/panzoom/blob/5a075a0/src/ • **x**: _number_ -_Defined in [types.ts:164](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L164)_ +_Defined in [types.ts:168](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L168)_ --- @@ -818,7 +820,7 @@ _Defined in [types.ts:164](https://github.com/timmywil/panzoom/blob/5a075a0/src/ • **y**: _number_ -_Defined in [types.ts:165](https://github.com/timmywil/panzoom/blob/5a075a0/src/types.ts#L165)_ +_Defined in [types.ts:169](https://github.com/timmywil/panzoom/blob/761a0ec/src/types.ts#L169)_ ## Events diff --git a/demo/global-panzoom.ts b/demo/global-panzoom.ts new file mode 100644 index 00000000..d4b3af1a --- /dev/null +++ b/demo/global-panzoom.ts @@ -0,0 +1,8 @@ +import Panzoom from '../src/panzoom' + +declare global { + interface Window { + Panzoom: typeof Panzoom + } +} +window.Panzoom = Panzoom diff --git a/demo/index.tsx b/demo/index.tsx index e3152e72..7df5d6f1 100644 --- a/demo/index.tsx +++ b/demo/index.tsx @@ -1,13 +1,15 @@ -import React from 'react' -import ReactDOM from 'react-dom' import './demo.css' +import './global-panzoom' + import ContainInside from './examples/ContainInside' import ContainOutside from './examples/ContainOutside' import DisabledYAxis from './examples/DisabledYAxis' import Exclude from './examples/Exclude' import Focal from './examples/Focal' -import Standard from './examples/Standard' +import React from 'react' +import ReactDOM from 'react-dom' import SVG from './examples/SVG' +import Standard from './examples/Standard' function Demos() { return ( diff --git a/src/panzoom.ts b/src/panzoom.ts index 344aaad9..04781062 100644 --- a/src/panzoom.ts +++ b/src/panzoom.ts @@ -152,7 +152,12 @@ function Panzoom( } } - function constrainXY(toX: number | string, toY: number | string, panOptions?: PanOptions) { + function constrainXY( + toX: number | string, + toY: number | string, + toScale: number, + panOptions?: PanOptions + ) { const opts = { ...options, ...panOptions } const result = { x, y, opts } if (!opts.force && (opts.disablePan || (opts.panOnlyWhenZoomed && scale === opts.startScale))) { @@ -175,7 +180,7 @@ function Panzoom( -dims.elem.margin.left - dims.parent.padding.left, Math.min( dims.parent.width - - dims.elem.width / scale - + dims.elem.width / toScale - dims.parent.padding.left - dims.elem.margin.left - dims.parent.border.left - @@ -187,7 +192,7 @@ function Panzoom( -dims.elem.margin.top - dims.parent.padding.top, Math.min( dims.parent.height - - dims.elem.height / scale - + dims.elem.height / toScale - dims.parent.padding.top - dims.elem.margin.top - dims.parent.border.top - @@ -197,26 +202,30 @@ function Panzoom( ) } else if (opts.contain === 'outside') { const dims = getDimensions(elem) - const diffHorizontal = (dims.elem.width - dims.elem.width / scale) / 2 - const diffVertical = (dims.elem.height - dims.elem.height / scale) / 2 - result.x = Math.max( - Math.min(result.x, (diffHorizontal - dims.parent.padding.left) / scale), - (-(dims.elem.width - dims.parent.width) - + const realWidth = dims.elem.width / scale + const realHeight = dims.elem.height / scale + const scaledWidth = realWidth * toScale + const scaledHeight = realHeight * toScale + const diffHorizontal = (scaledWidth - realWidth) / 2 + const diffVertical = (scaledHeight - realHeight) / 2 + const minX = + (-(scaledWidth - dims.parent.width) - dims.parent.padding.left - dims.parent.border.left - dims.parent.border.right + diffHorizontal) / - scale - ) - result.y = Math.max( - Math.min(result.y, (diffVertical - dims.parent.padding.top) / scale), - (-(dims.elem.height - dims.parent.height) - + toScale + const maxX = (diffHorizontal - dims.parent.padding.left) / toScale + result.x = Math.max(Math.min(result.x, maxX), minX) + const minY = + (-(scaledHeight - dims.parent.height) - dims.parent.padding.top - dims.parent.border.top - dims.parent.border.bottom + diffVertical) / - scale - ) + toScale + const maxY = (diffVertical - dims.parent.padding.top) / toScale + result.y = Math.max(Math.min(result.y, maxY), minY) } return result } @@ -232,7 +241,7 @@ function Panzoom( } function pan(toX: number | string, toY: number | string, panOptions?: PanOptions) { - const result = constrainXY(toX, toY, panOptions) + const result = constrainXY(toX, toY, scale, panOptions) const opts = result.opts x = result.x @@ -259,10 +268,10 @@ function Panzoom( toX = (focal.x / toScale - focal.x / scale + x * toScale) / toScale toY = (focal.y / toScale - focal.y / scale + y * toScale) / toScale } - scale = toScale - const panResult = constrainXY(toX, toY, { relative: false }) + const panResult = constrainXY(toX, toY, toScale, { relative: false, force: true }) x = panResult.x y = panResult.y + scale = toScale return setTransformWithEvent('panzoomzoom', opts) } @@ -355,10 +364,10 @@ function Panzoom( function reset(resetOptions?: PanzoomOptions) { const opts = { ...options, animate: true, ...resetOptions } - const panResult = constrainXY(opts.startX, opts.startY, opts) + scale = constrainScale(opts.startScale, opts).scale + const panResult = constrainXY(opts.startX, opts.startY, scale, opts) x = panResult.x y = panResult.y - scale = constrainScale(opts.startScale, opts).scale return setTransformWithEvent('panzoomreset', opts) } diff --git a/src/types.ts b/src/types.ts index 5a07e43b..2f8651ae 100644 --- a/src/types.ts +++ b/src/types.ts @@ -126,7 +126,11 @@ interface PanSpecificOptions { contain?: 'inside' | 'outside' /** The cursor style to set on the panzoom element */ cursor?: string - /** Disable panning functionality. Note: disablePan also disables focal point zooming */ + /** + * Disable panning functionality. + * Note: disablePan does not affect focal point zooming or the constrain option. + * The element will still pan accordingly. + */ disablePan?: boolean /** Pan only on the Y axis */ disableXAxis?: boolean diff --git a/webpack.config.js b/webpack.config.js index 8bf440b0..ec8fecb3 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,7 +5,8 @@ module.exports = { mode: 'development', devtool: 'eval-source-map', entry: { - 'demo/index.html': './demo/index.tsx' + 'demo/index.html': './demo/index.tsx', + panzoom: './demo/global-panzoom.ts' }, output: { path: __dirname + '/demo'