From 1571e99d489f2095dcec5988e20e115a2253adbc Mon Sep 17 00:00:00 2001 From: Timmy Willison <4timmywil@gmail.com> Date: Tue, 6 Aug 2019 12:17:19 -0400 Subject: [PATCH] feat(contain): add contain: 'outside' option --- README.md | 2 +- docs/README.md | 35 ++--- docs/globals.md | 4 +- docs/interfaces/_types_.miscoptions.md | 139 ++++++++++++++++++ docs/interfaces/_types_.panoptions.md | 81 ----------- docs/interfaces/_types_.panzoomobject.md | 50 ++++--- docs/interfaces/_types_.zoomoptions.md | 70 --------- docs/modules/_css_.md | 91 +++++++++--- docs/modules/_isattached_.md | 4 +- docs/modules/_issvgelement_.md | 6 +- docs/modules/_panzoom_.md | 60 ++++++-- docs/modules/_types_.md | 27 +++- src/panzoom.ts | 172 +++++++++++++++-------- src/types.ts | 6 +- test/demo/demo.css | 4 +- test/demo/examples/ContainOutside.tsx | 30 ++++ test/demo/index.tsx | 2 + 17 files changed, 478 insertions(+), 305 deletions(-) create mode 100644 docs/interfaces/_types_.miscoptions.md delete mode 100644 docs/interfaces/_types_.panoptions.md delete mode 100644 docs/interfaces/_types_.zoomoptions.md create mode 100644 test/demo/examples/ContainOutside.tsx diff --git a/README.md b/README.md index 73570dea..9842e6ea 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ One could implement transitions manually in those browsers using the `setTransfo ## Loading Panzoom -Panzoom uses (UMD)[https://github.com/umdjs/umd] and can be loaded a lot of ways. +Panzoom uses [UMD](https://github.com/umdjs/umd) and can be loaded a lot of ways. With ES6 imports: diff --git a/docs/README.md b/docs/README.md index 2dc71c12..912ab400 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -> **[@panzoom/core](README.md)** +> **[@panzoom/panzoom](README.md)** [Globals](globals.md) / @@ -37,7 +37,7 @@ One could implement transitions manually in those browsers using the `setTransfo ## Loading Panzoom -Panzoom uses (UMD)[https://github.com/umdjs/umd] and can be loaded a lot of ways. +Panzoom uses [UMD](https://github.com/umdjs/umd) and can be loaded a lot of ways. With ES6 imports: @@ -69,31 +69,16 @@ const panzoom = Panzoom('.panzoom', { ## FAQ -1\. How do I make it so that I never see the background behind the Panzoom element? [example](https://codepen.io/timmywil/pen/qjvBF) +1\. What is `transform-origin` and why is it added to the panzoom element? -- This can be done with the `contain` option. Set `contain` to `"invert"` or `"auto"` and make sure the Panzoom element is the same size or larger than its parent. +- The `transform-origin` is the origin from which transforms are applied. Panzoom ensures the defaults are set to what it expects to calculate focal point zooming. +- HTML elements default to '50% 50%'. +- SVG elements default to '0 0'. -```js -$('.panzoom-elements').panzoom({ - contain: 'invert', - minScale: 1 -}) -``` - -2\. How do I make links work if they're within a Panzoom element? [example](https://codepen.io/timmywil/pen/bFiqy) - -- Event propagation is stopped for `mousedown` and `touchstart` events in order to allow for Panzoom elements within Panzoom elements. To fix the links, bind an event handler that prevents the event from reaching the Panzoom handler: - -```js -$('.panzoom a').on('mousedown touchstart', function(e) { - e.stopImmediatePropagation() -}) -``` - -3\. What is `transform-origin` and why is it set to `'0 0'` on the panzoom element? +2\. I am using Panzoom with an `` tag. It zooms but does not pan. [example](https://codepen.io/timmywil/pen/qNpykA) -- The `transform-origin` is the origin from which transforms are applied. The default for SVG is already `'0 0'`. Panzoom normalizes HTML to the same default, which makes working with both much simpler. The SVG default was chosen over the HTML one because changing the `transform-origin` on SVG elements doesn't work in IE. Anything that can be done with a `transform-origin` of `'50% 50%'` can be done with `'0 0'`; the transform values just need adjusting. +Object elements can eat up events, making it so they never reach Panzoom. To fix this, disable pointer events (`pointer-events: none`) on the `` tag and call Panzoom using a wrapper. -4\. I am using Panzoom with an `` tag. It zooms but does not pan. [example](https://codepen.io/timmywil/pen/qNpykA) +3\. My links aren't working! How do I enable an anchor within a panzoom element? -Object elements can eat up events, making it so they never reach Panzoom. To fix this, disable pointer events (`pointer-events: none`) on the `` tag and call Panzoom using a wrapper. \ No newline at end of file +Add class `options.clickable` (default is `"clickable"`) to whatever element you want to be clickable. This will add a listener that calls `event.stopImmediatePropagation()` to prevent the event from reaching panzoom. You could also do this yourself. \ No newline at end of file diff --git a/docs/globals.md b/docs/globals.md index 4a0c7f99..41d1f158 100644 --- a/docs/globals.md +++ b/docs/globals.md @@ -1,8 +1,8 @@ -> **[@panzoom/core](README.md)** +> **[@panzoom/panzoom](README.md)** [Globals](globals.md) / -# @panzoom/core +# @panzoom/panzoom ## Index diff --git a/docs/interfaces/_types_.miscoptions.md b/docs/interfaces/_types_.miscoptions.md new file mode 100644 index 00000000..e6ec1989 --- /dev/null +++ b/docs/interfaces/_types_.miscoptions.md @@ -0,0 +1,139 @@ +> **[@panzoom/panzoom](../README.md)** + +[Globals](../globals.md) / ["types"](../modules/_types_.md) / [MiscOptions](_types_.miscoptions.md) / + +# Interface: MiscOptions + +## Hierarchy + +* **MiscOptions** + +## Indexable + +● \[▪ **key**: *string*\]: any + +Pass through any options like data + +## Index + +### Properties + +* [animate](_types_.miscoptions.md#optional-animate) +* [clickableClass](_types_.miscoptions.md#optional-clickableclass) +* [duration](_types_.miscoptions.md#optional-duration) +* [easing](_types_.miscoptions.md#optional-easing) +* [origin](_types_.miscoptions.md#optional-origin) +* [setTransform](_types_.miscoptions.md#optional-settransform) +* [startScale](_types_.miscoptions.md#optional-startscale) +* [startX](_types_.miscoptions.md#optional-startx) +* [startY](_types_.miscoptions.md#optional-starty) + +## Properties + +### `Optional` animate + +• **animate**? : *boolean* + +*Defined in [types.ts:5](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L5)* + +Whether to animate transitions + +___ + +### `Optional` clickableClass + +• **clickableClass**? : *string* + +*Defined in [types.ts:10](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L10)* + +Add this class to any element within the panzoom element +that you want to be clickable and not initiate the drag + +___ + +### `Optional` duration + +• **duration**? : *number* + +*Defined in [types.ts:12](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L12)* + +Duration of the transition (ms) + +___ + +### `Optional` easing + +• **easing**? : *string* + +*Defined in [types.ts:14](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L14)* + +CSS Easing used for transitions + +___ + +### `Optional` origin + +• **origin**? : *string* + +*Defined in [types.ts:28](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L28)* + +**Change this at your own risk.** +The `transform-origin` is the origin from which transforms are applied. +Default: `'50% 50%'` for HTML and `'0 0'` for SVG. +The defaults are set because changing the `transform-origin` on +SVG elements doesn't work in IE. + +Changing this should work with most things, but +it will break focal point zooming, which assumes the +defaults are set to do the more complicated calculations. + +And again, changing this for SVG in IE doesn't work at all. + +___ + +### `Optional` setTransform + +• **setTransform**? : *[setTransform](../modules/_css_.md#settransform)* + +*Defined in [types.ts:45](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L45)* + +Override the transform setter +This is exposed mostly so the user could +set other parts of a transform +aside from scale and translate. + +```js +// This example always sets a rotation +// when setting the scale and translation +Panzoom(elem, { + setTransform: (elem, { scale, x, y }) => { + setStyle(elem, 'transform', `rotate(0.5turn) scale(${scale}) translate(${x}px, ${y}px)`) + } +}) +``` + +___ + +### `Optional` startScale + +• **startScale**? : *number* + +*Defined in [types.ts:49](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L49)* + +___ + +### `Optional` startX + +• **startX**? : *number* + +*Defined in [types.ts:47](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L47)* + +Values used to set the beginning transform + +___ + +### `Optional` startY + +• **startY**? : *number* + +*Defined in [types.ts:48](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L48)* \ No newline at end of file diff --git a/docs/interfaces/_types_.panoptions.md b/docs/interfaces/_types_.panoptions.md deleted file mode 100644 index 1dc5a34a..00000000 --- a/docs/interfaces/_types_.panoptions.md +++ /dev/null @@ -1,81 +0,0 @@ -> **[@panzoom/core](../README.md)** - -[Globals](../globals.md) / ["types"](../modules/_types_.md) / [PanOptions](_types_.panoptions.md) / - -# Interface: PanOptions - -## Hierarchy - -* **PanOptions** - -## Index - -### Properties - -* [cursor](_types_.panoptions.md#optional-cursor) -* [disablePan](_types_.panoptions.md#optional-disablepan) -* [disableXAxis](_types_.panoptions.md#optional-disablexaxis) -* [disableYAxis](_types_.panoptions.md#optional-disableyaxis) -* [relative](_types_.panoptions.md#optional-relative) -* [skipUpdate](_types_.panoptions.md#optional-skipupdate) - -## Properties - -### `Optional` cursor - -• **cursor**? : *string* - -*Defined in [types.ts:13](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L13)* - -The cursor style to set on the panzoom element - -___ - -### `Optional` disablePan - -• **disablePan**? : *boolean* - -*Defined in [types.ts:5](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L5)* - -Disable panning functionality. Note: disablePan also disables focal point zooming - -___ - -### `Optional` disableXAxis - -• **disableXAxis**? : *boolean* - -*Defined in [types.ts:7](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L7)* - -Pan only on the Y axis - -___ - -### `Optional` disableYAxis - -• **disableYAxis**? : *boolean* - -*Defined in [types.ts:9](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L9)* - -Pan only on the X axis - -___ - -### `Optional` relative - -• **relative**? : *boolean* - -*Defined in [types.ts:11](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L11)* - -When passing x and y values to .pan(), treat the values as relative to their current values - -___ - -### `Optional` skipUpdate - -• **skipUpdate**? : *boolean* - -*Defined in [types.ts:18](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L18)* - -Set relevant Panzoom internal values without -actually updating the transform \ No newline at end of file diff --git a/docs/interfaces/_types_.panzoomobject.md b/docs/interfaces/_types_.panzoomobject.md index 438ae6fa..595e4bcb 100644 --- a/docs/interfaces/_types_.panzoomobject.md +++ b/docs/interfaces/_types_.panzoomobject.md @@ -1,4 +1,4 @@ -> **[@panzoom/core](../README.md)** +> **[@panzoom/panzoom](../README.md)** [Globals](../globals.md) / ["types"](../modules/_types_.md) / [PanzoomObject](_types_.panzoomobject.md) / @@ -30,7 +30,7 @@ • **getPan**: *function* -*Defined in [types.ts:66](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L66)* +*Defined in [types.ts:100](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L100)* Get the current x/y translation @@ -48,7 +48,7 @@ ___ • **getScale**: *function* -*Defined in [types.ts:68](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L68)* +*Defined in [types.ts:102](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L102)* Get the current scale @@ -62,7 +62,7 @@ ___ • **options**: *[PanzoomOptions](../modules/_types_.md#panzoomoptions)* -*Defined in [types.ts:118](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L118)* +*Defined in [types.ts:152](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L152)* The contructed options for this Panzoom instance @@ -72,7 +72,7 @@ ___ • **pan**: *function* -*Defined in [types.ts:79](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L79)* +*Defined in [types.ts:113](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L113)* Pan the Panzoom element to the given x and y coordinates @@ -85,7 +85,7 @@ panzoom.pan(10, 10, { relative: true }) #### Type declaration: -▸ (`x`: number | string, `y`: number | string, `panOptions?`: [PanOptions](_types_.panoptions.md)): *void* +▸ (`x`: number | string, `y`: number | string, `panOptions?`: [PanOptions](../modules/_types_.md#panoptions)): *void* **Parameters:** @@ -93,7 +93,7 @@ Name | Type | ------ | ------ | `x` | number \| string | `y` | number \| string | -`panOptions?` | [PanOptions](_types_.panoptions.md) | +`panOptions?` | [PanOptions](../modules/_types_.md#panoptions) | ___ @@ -101,13 +101,19 @@ ___ • **reset**: *function* -*Defined in [types.ts:122](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L122)* +*Defined in [types.ts:156](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L156)* -Reset the pan and zoom to 0 +Reset the pan and zoom to startX, startY, and startScale #### Type declaration: -▸ (): *void* +▸ (`options?`: [PanzoomOptions](../modules/_types_.md#panzoomoptions)): *void* + +**Parameters:** + +Name | Type | +------ | ------ | +`options?` | [PanzoomOptions](../modules/_types_.md#panzoomoptions) | ___ @@ -115,7 +121,7 @@ ___ • **setOptions**: *function* -*Defined in [types.ts:120](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L120)* +*Defined in [types.ts:154](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L154)* Change options for the Panzoom instance @@ -135,7 +141,7 @@ ___ • **setStyle**: *[setStyle](../modules/_css_.md#setstyle)* -*Defined in [types.ts:124](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L124)* +*Defined in [types.ts:158](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L158)* A convenience method for setting prefixed styles on the Panzoom element @@ -145,7 +151,7 @@ ___ • **zoom**: *function* -*Defined in [types.ts:96](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L96)* +*Defined in [types.ts:130](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L130)* Zoom the Panzoom element to the given scale @@ -156,14 +162,14 @@ panzoom.zoom(2.2, { animate: true }) #### Type declaration: -▸ (`scale`: number, `zoomOptions?`: [ZoomOptions](_types_.zoomoptions.md)): *void* +▸ (`scale`: number, `zoomOptions?`: [ZoomOptions](../modules/_types_.md#zoomoptions)): *void* **Parameters:** Name | Type | ------ | ------ | `scale` | number | -`zoomOptions?` | [ZoomOptions](_types_.zoomoptions.md) | +`zoomOptions?` | [ZoomOptions](../modules/_types_.md#zoomoptions) | ___ @@ -171,19 +177,19 @@ ___ • **zoomIn**: *function* -*Defined in [types.ts:83](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L83)* +*Defined in [types.ts:117](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L117)* Zoom in using the predetermined increment set in options #### Type declaration: -▸ (`zoomOptions?`: [ZoomOptions](_types_.zoomoptions.md)): *void* +▸ (`zoomOptions?`: [ZoomOptions](../modules/_types_.md#zoomoptions)): *void* **Parameters:** Name | Type | ------ | ------ | -`zoomOptions?` | [ZoomOptions](_types_.zoomoptions.md) | +`zoomOptions?` | [ZoomOptions](../modules/_types_.md#zoomoptions) | ___ @@ -191,19 +197,19 @@ ___ • **zoomOut**: *function* -*Defined in [types.ts:87](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L87)* +*Defined in [types.ts:121](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L121)* Zoom out using the predetermined increment set in options #### Type declaration: -▸ (`zoomOptions?`: [ZoomOptions](_types_.zoomoptions.md)): *void* +▸ (`zoomOptions?`: [ZoomOptions](../modules/_types_.md#zoomoptions)): *void* **Parameters:** Name | Type | ------ | ------ | -`zoomOptions?` | [ZoomOptions](_types_.zoomoptions.md) | +`zoomOptions?` | [ZoomOptions](../modules/_types_.md#zoomoptions) | ___ @@ -211,7 +217,7 @@ ___ • **zoomWithWheel**: *function* -*Defined in [types.ts:116](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L116)* +*Defined in [types.ts:150](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L150)* Zoom the Panzoom element to a focal point using the given WheelEvent diff --git a/docs/interfaces/_types_.zoomoptions.md b/docs/interfaces/_types_.zoomoptions.md deleted file mode 100644 index 5cbfa686..00000000 --- a/docs/interfaces/_types_.zoomoptions.md +++ /dev/null @@ -1,70 +0,0 @@ -> **[@panzoom/core](../README.md)** - -[Globals](../globals.md) / ["types"](../modules/_types_.md) / [ZoomOptions](_types_.zoomoptions.md) / - -# Interface: ZoomOptions - -## Hierarchy - -* **ZoomOptions** - -## Index - -### Properties - -* [disableZoom](_types_.zoomoptions.md#optional-disablezoom) -* [maxScale](_types_.zoomoptions.md#optional-maxscale) -* [minScale](_types_.zoomoptions.md#optional-minscale) -* [skipUpdate](_types_.zoomoptions.md#optional-skipupdate) -* [step](_types_.zoomoptions.md#optional-step) - -## Properties - -### `Optional` disableZoom - -• **disableZoom**? : *boolean* - -*Defined in [types.ts:23](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L23)* - -Disable zooming functionality - -___ - -### `Optional` maxScale - -• **maxScale**? : *number* - -*Defined in [types.ts:27](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L27)* - -The maximum scale when zooming - -___ - -### `Optional` minScale - -• **minScale**? : *number* - -*Defined in [types.ts:25](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L25)* - -The minimum scale when zooming - -___ - -### `Optional` skipUpdate - -• **skipUpdate**? : *boolean* - -*Defined in [types.ts:34](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L34)* - -Set relevant Panzoom internal values without -actually updating the transform - -___ - -### `Optional` step - -• **step**? : *number* - -*Defined in [types.ts:29](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L29)* - -The step affects the rate of zooming with a mouse wheel, pinching, or range element \ No newline at end of file diff --git a/docs/modules/_css_.md b/docs/modules/_css_.md index 7bf5efa0..33605962 100644 --- a/docs/modules/_css_.md +++ b/docs/modules/_css_.md @@ -1,4 +1,4 @@ -> **[@panzoom/core](../README.md)** +> **[@panzoom/panzoom](../README.md)** [Globals](../globals.md) / ["css"](_css_.md) / @@ -14,12 +14,14 @@ ### Functions +* [getBorder](_css_.md#getborder) * [getCSSNum](_css_.md#getcssnum) +* [getMargin](_css_.md#getmargin) * [getPadding](_css_.md#getpadding) * [getPrefixedName](_css_.md#getprefixedname) * [setStyle](_css_.md#setstyle) * [setTransform](_css_.md#settransform) -* [setTransformOrigin](_css_.md#settransformorigin) +* [setTransition](_css_.md#settransition) ## Variables @@ -27,7 +29,7 @@ • **divStyle**: *`CSSStyleDeclaration`* = document.createElement('div').style -*Defined in [css.ts:4](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L4)* +*Defined in [css.ts:6](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L6)* Proper prefixing for cross-browser compatibility @@ -37,7 +39,7 @@ ___ • **prefixCache**: *object* -*Defined in [css.ts:6](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L6)* +*Defined in [css.ts:8](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L8)* #### Type declaration: @@ -49,15 +51,40 @@ ___ • **prefixes**: *string[]* = ['webkit', 'moz', 'ms'] -*Defined in [css.ts:5](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L5)* +*Defined in [css.ts:7](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L7)* ## Functions +### getBorder + +▸ **getBorder**(`elem`: `HTMLElement` | `SVGElement`, `style?`: `CSSStyleDeclaration`): *object* + +*Defined in [css.ts:45](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L45)* + +**Parameters:** + +Name | Type | +------ | ------ | +`elem` | `HTMLElement` \| `SVGElement` | +`style?` | `CSSStyleDeclaration` | + +**Returns:** *object* + +* **bottom**: *number* = getCSSNum(style, 'borderBottom') + +* **left**: *number* = getCSSNum(style, 'borderLeft') + +* **right**: *number* = getCSSNum(style, 'borderRight') + +* **top**: *number* = getCSSNum(style, 'borderTop') + +___ + ### getCSSNum ▸ **getCSSNum**(`style`: `CSSStyleDeclaration`, `name`: string): *number* -*Defined in [css.ts:25](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L25)* +*Defined in [css.ts:29](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L29)* Gets a style value expected to be a number @@ -72,17 +99,43 @@ Name | Type | ___ +### getMargin + +▸ **getMargin**(`elem`: `HTMLElement` | `SVGElement`, `style?`: `CSSStyleDeclaration`): *object* + +*Defined in [css.ts:57](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L57)* + +**Parameters:** + +Name | Type | +------ | ------ | +`elem` | `HTMLElement` \| `SVGElement` | +`style?` | `CSSStyleDeclaration` | + +**Returns:** *object* + +* **bottom**: *number* = getCSSNum(style, 'marginBottom') + +* **left**: *number* = getCSSNum(style, 'marginLeft') + +* **right**: *number* = getCSSNum(style, 'marginRight') + +* **top**: *number* = getCSSNum(style, 'marginTop') + +___ + ### getPadding -▸ **getPadding**(`elem`: `HTMLElement` | `SVGElement`): *object* +▸ **getPadding**(`elem`: `HTMLElement` | `SVGElement`, `style?`: `CSSStyleDeclaration`): *object* -*Defined in [css.ts:29](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L29)* +*Defined in [css.ts:33](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L33)* **Parameters:** Name | Type | ------ | ------ | `elem` | `HTMLElement` \| `SVGElement` | +`style?` | `CSSStyleDeclaration` | **Returns:** *object* @@ -100,7 +153,7 @@ ___ ▸ **getPrefixedName**(`name`: string): *string* -*Defined in [css.ts:7](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L7)* +*Defined in [css.ts:9](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L9)* **Parameters:** @@ -116,7 +169,7 @@ ___ ▸ **setStyle**(`elem`: `HTMLElement` | `SVGElement`, `name`: string, `value`: string): *void* -*Defined in [css.ts:42](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L42)* +*Defined in [css.ts:72](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L72)* Set a style using the properly prefixed name @@ -134,9 +187,9 @@ ___ ### setTransform -▸ **setTransform**(`elem`: `HTMLElement` | `SVGElement`, `__namedParameters`: object): *void* +▸ **setTransform**(`elem`: `HTMLElement` | `SVGElement`, `__namedParameters`: object, `options`: [PanzoomOptions](_types_.md#panzoomoptions)): *void* -*Defined in [css.ts:58](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L58)* +*Defined in [css.ts:89](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L89)* Set the transform using the proper prefix @@ -152,24 +205,26 @@ Name | Type | `x` | number | `y` | number | +▪`Default value` **options**: *[PanzoomOptions](_types_.md#panzoomoptions)*= {} + **Returns:** *void* ___ -### setTransformOrigin +### setTransition -▸ **setTransformOrigin**(`elem`: `HTMLElement` | `SVGElement`): *void* +▸ **setTransition**(`elem`: `HTMLElement` | `SVGElement`, `options`: [PanzoomOptions](_types_.md#panzoomoptions)): *void* -*Defined in [css.ts:51](https://github.com/timmywil/panzoom/blob/54eb41a/src/css.ts#L51)* +*Defined in [css.ts:80](https://github.com/timmywil/panzoom/blob/a7078e8/src/css.ts#L80)* -Sets the default transform-origin for both HTML and SVG to 0 0 -SVG transform-origin cannot be changed to 50% 50% in IE9-11 or Edge 13-14+, -so we default to 0 0 for everything. +Constructs the transition from panzoom options +and takes care of prefixing the transition and transform **Parameters:** Name | Type | ------ | ------ | `elem` | `HTMLElement` \| `SVGElement` | +`options` | [PanzoomOptions](_types_.md#panzoomoptions) | **Returns:** *void* \ No newline at end of file diff --git a/docs/modules/_isattached_.md b/docs/modules/_isattached_.md index 29e7c5f8..5b700884 100644 --- a/docs/modules/_isattached_.md +++ b/docs/modules/_isattached_.md @@ -1,4 +1,4 @@ -> **[@panzoom/core](../README.md)** +> **[@panzoom/panzoom](../README.md)** [Globals](../globals.md) / ["isAttached"](_isattached_.md) / @@ -16,7 +16,7 @@ ▸ **isAttached**(`elem`: `HTMLElement` | `SVGElement`): *boolean* -*Defined in [isAttached.ts:5](https://github.com/timmywil/panzoom/blob/54eb41a/src/isAttached.ts#L5)* +*Defined in [isAttached.ts:5](https://github.com/timmywil/panzoom/blob/a7078e8/src/isAttached.ts#L5)* Determine if an element is attached to the DOM Panzoom requires this so events work properly diff --git a/docs/modules/_issvgelement_.md b/docs/modules/_issvgelement_.md index 6f63d87a..d5522d56 100644 --- a/docs/modules/_issvgelement_.md +++ b/docs/modules/_issvgelement_.md @@ -1,4 +1,4 @@ -> **[@panzoom/core](../README.md)** +> **[@panzoom/panzoom](../README.md)** [Globals](../globals.md) / ["isSVGElement"](_issvgelement_.md) / @@ -20,7 +20,7 @@ • **rsvg**: *`RegExp`* = /^http:[\w\.\/]+svg$/ -*Defined in [isSVGElement.ts:5](https://github.com/timmywil/panzoom/blob/54eb41a/src/isSVGElement.ts#L5)* +*Defined in [isSVGElement.ts:5](https://github.com/timmywil/panzoom/blob/a7078e8/src/isSVGElement.ts#L5)* Determine if an element is SVG by checking the namespace Exception: the element itself should be treated like HTML @@ -31,7 +31,7 @@ Exception: the element itself should be treated like HTML ▸ **isSVGElement**(`elem`: `HTMLElement` | `SVGElement`): *boolean* -*Defined in [isSVGElement.ts:6](https://github.com/timmywil/panzoom/blob/54eb41a/src/isSVGElement.ts#L6)* +*Defined in [isSVGElement.ts:6](https://github.com/timmywil/panzoom/blob/a7078e8/src/isSVGElement.ts#L6)* **Parameters:** diff --git a/docs/modules/_panzoom_.md b/docs/modules/_panzoom_.md index a57c55ef..0a46782b 100644 --- a/docs/modules/_panzoom_.md +++ b/docs/modules/_panzoom_.md @@ -1,4 +1,4 @@ -> **[@panzoom/core](../README.md)** +> **[@panzoom/panzoom](../README.md)** [Globals](../globals.md) / ["panzoom"](_panzoom_.md) / @@ -20,7 +20,7 @@ ▸ **Panzoom**(`elem`: `HTMLElement` | `SVGElement`, `options?`: [PanzoomOptions](_types_.md#panzoomoptions)): *[PanzoomObject](../interfaces/_types_.panzoomobject.md)* -*Defined in [panzoom.ts:29](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L29)* +*Defined in [panzoom.ts:35](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L35)* **Parameters:** @@ -37,76 +37,106 @@ Name | Type | ### ▪ **defaultOptions**: *object* -*Defined in [panzoom.ts:14](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L14)* +*Defined in [panzoom.ts:15](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L15)* ### animate • **animate**: *false* = false -*Defined in [panzoom.ts:15](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L15)* +*Defined in [panzoom.ts:16](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L16)* + +### clickableClass + +• **clickableClass**: *string* = "clickable" + +*Defined in [panzoom.ts:17](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L17)* ### cursor • **cursor**: *string* = "move" -*Defined in [panzoom.ts:16](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L16)* +*Defined in [panzoom.ts:18](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L18)* ### disablePan • **disablePan**: *false* = false -*Defined in [panzoom.ts:17](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L17)* +*Defined in [panzoom.ts:19](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L19)* ### disableXAxis • **disableXAxis**: *false* = false -*Defined in [panzoom.ts:19](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L19)* +*Defined in [panzoom.ts:21](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L21)* ### disableYAxis • **disableYAxis**: *false* = false -*Defined in [panzoom.ts:20](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L20)* +*Defined in [panzoom.ts:22](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L22)* ### disableZoom • **disableZoom**: *false* = false -*Defined in [panzoom.ts:18](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L18)* +*Defined in [panzoom.ts:20](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L20)* + +### duration + +• **duration**: *number* = 200 + +*Defined in [panzoom.ts:23](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L23)* ### easing • **easing**: *string* = "ease-in-out" -*Defined in [panzoom.ts:21](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L21)* +*Defined in [panzoom.ts:24](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L24)* ### maxScale • **maxScale**: *number* = 4 -*Defined in [panzoom.ts:22](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L22)* +*Defined in [panzoom.ts:25](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L25)* ### minScale • **minScale**: *number* = 0.125 -*Defined in [panzoom.ts:23](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L23)* +*Defined in [panzoom.ts:26](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L26)* ### relative • **relative**: *false* = false -*Defined in [panzoom.ts:24](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L24)* +*Defined in [panzoom.ts:27](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L27)* ### setTransform • **setTransform**: *[setTransform](_css_.md#settransform)* -*Defined in [panzoom.ts:25](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L25)* +*Defined in [panzoom.ts:28](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L28)* + +### startScale + +• **startScale**: *number* = 1 + +*Defined in [panzoom.ts:31](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L31)* + +### startX + +• **startX**: *number* = 0 + +*Defined in [panzoom.ts:29](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L29)* + +### startY + +• **startY**: *number* = 0 + +*Defined in [panzoom.ts:30](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L30)* ### step • **step**: *number* = 0.1 -*Defined in [panzoom.ts:26](https://github.com/timmywil/panzoom/blob/54eb41a/src/panzoom.ts#L26)* \ No newline at end of file +*Defined in [panzoom.ts:32](https://github.com/timmywil/panzoom/blob/a7078e8/src/panzoom.ts#L32)* \ No newline at end of file diff --git a/docs/modules/_types_.md b/docs/modules/_types_.md index c32ca3d5..4064fbdc 100644 --- a/docs/modules/_types_.md +++ b/docs/modules/_types_.md @@ -1,4 +1,4 @@ -> **[@panzoom/core](../README.md)** +> **[@panzoom/panzoom](../README.md)** [Globals](../globals.md) / ["types"](_types_.md) / @@ -8,18 +8,35 @@ ### Interfaces -* [PanOptions](../interfaces/_types_.panoptions.md) +* [MiscOptions](../interfaces/_types_.miscoptions.md) * [PanzoomObject](../interfaces/_types_.panzoomobject.md) -* [ZoomOptions](../interfaces/_types_.zoomoptions.md) ### Type aliases +* [PanOptions](_types_.md#panoptions) * [PanzoomOptions](_types_.md#panzoomoptions) +* [ZoomOptions](_types_.md#zoomoptions) ## Type aliases +### PanOptions + +Ƭ **PanOptions**: *[MiscOptions](../interfaces/_types_.miscoptions.md) & object* + +*Defined in [types.ts:54](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L54)* + +___ + ### PanzoomOptions -Ƭ **PanzoomOptions**: *[PanOptions](../interfaces/_types_.panoptions.md) & [ZoomOptions](../interfaces/_types_.zoomoptions.md) & object* +Ƭ **PanzoomOptions**: *[PanOptions](_types_.md#panoptions) & [ZoomOptions](_types_.md#zoomoptions)* + +*Defined in [types.ts:96](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L96)* + +___ + +### ZoomOptions + +Ƭ **ZoomOptions**: *[MiscOptions](../interfaces/_types_.miscoptions.md) & object* -*Defined in [types.ts:37](https://github.com/timmywil/panzoom/blob/54eb41a/src/types.ts#L37)* \ No newline at end of file +*Defined in [types.ts:78](https://github.com/timmywil/panzoom/blob/a7078e8/src/types.ts#L78)* \ No newline at end of file diff --git a/src/panzoom.ts b/src/panzoom.ts index 3e248d84..a5dfd68c 100644 --- a/src/panzoom.ts +++ b/src/panzoom.ts @@ -26,6 +26,9 @@ const defaultOptions: PanzoomOptions = { minScale: 0.125, relative: false, setTransform, + startX: 0, + startY: 0, + startScale: 1, step: 0.1 } @@ -57,6 +60,10 @@ function Panzoom(elem: HTMLElement | SVGElement, options?: PanzoomOptions): Panz } } + // Set overflow on the parent + const parent = elem.parentElement + parent.style.overflow = 'hidden' + // Set some default styles on the panzoom element elem.style.cursor = options.cursor // The default for HTML is '50% 50%' @@ -68,14 +75,52 @@ function Panzoom(elem: HTMLElement | SVGElement, options?: PanzoomOptions): Panz typeof options.origin === 'string' ? options.origin : isSVG ? '0 0' : '50% 50%' ) - // Set overflow on the parent - const parent = elem.parentElement - parent.style.overflow = 'hidden' - let x = 0 let y = 0 let scale = 1 let isPanning = false + zoom(options.startScale, { animate: false }) + // Wait for scale to update + // for accurate dimensions + // to constrain initial values + setTimeout(() => { + pan(options.startX, options.startY, { animate: false }) + }) + + /** + * Dimensions used in containment and focal point zooming + */ + function getDimensions() { + const style = window.getComputedStyle(elem) + const parentStyle = window.getComputedStyle(parent) + const rectElem = elem.getBoundingClientRect() + const rectParent = parent.getBoundingClientRect() + + return { + elem: { + style, + width: rectElem.width, + height: rectElem.height, + top: rectElem.top, + bottom: rectElem.bottom, + left: rectElem.left, + right: rectElem.right, + margin: getMargin(elem, style), + border: getBorder(elem, style) + }, + parent: { + style: parentStyle, + width: rectParent.width, + height: rectParent.height, + top: rectParent.top, + bottom: rectParent.bottom, + left: rectParent.left, + right: rectParent.right, + padding: getPadding(parent, parentStyle), + border: getBorder(parent, parentStyle) + } + } + } function constrainXY(toX: number | string, toY: number | string, panOptions?: PanOptions) { const opts = { ...options, ...panOptions } @@ -95,38 +140,53 @@ function Panzoom(elem: HTMLElement | SVGElement, options?: PanzoomOptions): Panz } if (opts.contain === 'inside') { - const rect = elem.getBoundingClientRect() - const style = window.getComputedStyle(elem) - const margin = getMargin(elem, style) - const border = getBorder(elem, style) - const parentStyle = window.getComputedStyle(parent) - const parentPadding = getPadding(parent, parentStyle) - const parentBorder = getBorder(parent, parentStyle) - const parentRect = parent.getBoundingClientRect() + const dims = getDimensions() result.x = Math.max( - -margin.left - parentPadding.left, + -dims.elem.margin.left - dims.parent.padding.left, Math.min( - parentRect.width - - rect.width / scale - - parentPadding.left - - margin.left - - parentBorder.left - - border.left, + dims.parent.width - + dims.elem.width / scale - + dims.parent.padding.left - + dims.elem.margin.left - + dims.parent.border.left - + dims.parent.border.right, result.x ) ) result.y = Math.max( - -margin.top - parentPadding.top, + -dims.elem.margin.top - dims.parent.padding.top, Math.min( - parentRect.height - - rect.height / scale - - parentPadding.top - - margin.top - - parentBorder.top - - border.left, + dims.parent.height - + dims.elem.height / scale - + dims.parent.padding.top - + dims.elem.margin.top - + dims.parent.border.top - + dims.parent.border.bottom, result.y ) ) + } else if (opts.contain === 'outside') { + const dims = getDimensions() + 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) - + 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) - + dims.parent.padding.top - + dims.parent.border.top - + dims.parent.border.bottom + + diffVertical) / + scale + ) } return result } @@ -198,13 +258,7 @@ function Panzoom(elem: HTMLElement | SVGElement, options?: PanzoomOptions): Panz const wheel = delta < 0 ? 1 : -1 const toScale = constrainScale(scale * Math.exp(wheel * options.step)).scale - // Get the position of point over the element before the scale - const rect = elem.getBoundingClientRect() - const margin = getMargin(elem) - const parentRect = parent.getBoundingClientRect() - const parentStyle = window.getComputedStyle(parent) - const parentPadding = getPadding(parent, parentStyle) - const parentBorder = getBorder(parent, parentStyle) + const dims = getDimensions() // Instead of thinking of operating on the panzoom element, // think of operating on the area inside the panzoom @@ -212,30 +266,39 @@ function Panzoom(elem: HTMLElement | SVGElement, options?: PanzoomOptions): Panz // Subtract padding and border const effectiveArea = { width: - parentRect.width - - parentPadding.left - - parentPadding.right - - parentBorder.left - - parentBorder.right, + dims.parent.width - + dims.parent.padding.left - + dims.parent.padding.right - + dims.parent.border.left - + dims.parent.border.right, height: - parentRect.height - - parentPadding.top - - parentPadding.bottom - - parentBorder.top - - parentBorder.bottom + dims.parent.height - + dims.parent.padding.top - + dims.parent.padding.bottom - + dims.parent.border.top - + dims.parent.border.bottom } // Adjust the clientX/clientY to ignore the area // outside the effective area let clientX = - event.clientX - parentRect.left - parentPadding.left - parentBorder.left - margin.left - let clientY = event.clientY - parentRect.top - parentPadding.top - parentBorder.top - margin.top + event.clientX - + dims.parent.left - + dims.parent.padding.left - + dims.parent.border.left - + dims.elem.margin.left + let clientY = + event.clientY - + dims.parent.top - + dims.parent.padding.top - + dims.parent.border.top - + dims.elem.margin.top // Adjust the clientX/clientY for HTML elements, // because they have a transform-origin of 50% 50% if (!isSVG) { - clientX -= rect.width / scale / 2 - clientY -= rect.height / scale / 2 + clientX -= dims.elem.width / scale / 2 + clientY -= dims.elem.height / scale / 2 } // The new width after the scale @@ -254,19 +317,12 @@ function Panzoom(elem: HTMLElement | SVGElement, options?: PanzoomOptions): Panz } function reset(resetOptions?: PanzoomOptions) { - const panResult = constrainXY(0, 0, resetOptions) + const opts = { ...options, animate: true, ...resetOptions } + const panResult = constrainXY(opts.startX, opts.startY, opts) x = panResult.x y = panResult.y - scale = constrainScale(1, resetOptions).scale - options.setTransform( - elem, - { x, y, scale }, - { - ...options, - animate: true, - ...resetOptions - } - ) + scale = constrainScale(opts.startScale, opts).scale + options.setTransform(elem, { x, y, scale }, opts) } function startMove(startEvent: PointerEvent) { diff --git a/src/types.ts b/src/types.ts index 4940aba5..913fcf06 100644 --- a/src/types.ts +++ b/src/types.ts @@ -43,6 +43,10 @@ interface MiscOptions { * ``` */ setTransform?: typeof setTransform + /** Values used to set the beginning transform */ + startX?: number /* Default: 0 */ + startY?: number /* Default: 0 */ + startScale?: number /* Default: 1 */ /** Pass through any options like data */ [key: string]: any } @@ -148,7 +152,7 @@ export interface PanzoomObject { options: PanzoomOptions /** Change options for the Panzoom instance */ setOptions: (options?: PanzoomOptions) => void - /** Reset the pan and zoom to 0 */ + /** Reset the pan and zoom to startX, startY, and startScale */ reset: (options?: PanzoomOptions) => void /** A convenience method for setting prefixed styles on the Panzoom element */ setStyle: typeof setStyle diff --git a/test/demo/demo.css b/test/demo/demo.css index 93cd3725..1970198f 100644 --- a/test/demo/demo.css +++ b/test/demo/demo.css @@ -49,8 +49,8 @@ pre { position: relative; box-shadow: inset 0 0 5px rgba(223, 212, 212, 0.5); margin: 30px; - padding: 20px 20px 50px; - border: 3px solid black; + padding: 80px; + border: 20px solid black; border-radius: 5px; } .panzoom { diff --git a/test/demo/examples/ContainOutside.tsx b/test/demo/examples/ContainOutside.tsx new file mode 100644 index 00000000..9d0db3c0 --- /dev/null +++ b/test/demo/examples/ContainOutside.tsx @@ -0,0 +1,30 @@ +import React, { useEffect, useRef } from 'react' +import Panzoom from '../../../src/panzoom' +import Code from '../Code' +import Demo from '../Demo' + +const code = {`Panzoom(elem, { contain: 'outside', startScale: 1.5 })`} + +export default function ContainOutside() { + const elem = useRef(null) + useEffect(() => { + Panzoom(elem.current, { contain: 'outside', startScale: 1.5 }) + }, []) + return ( + +
+
+ +
+
+
+ ) +} diff --git a/test/demo/index.tsx b/test/demo/index.tsx index 1f63569c..ea126cca 100644 --- a/test/demo/index.tsx +++ b/test/demo/index.tsx @@ -2,6 +2,7 @@ import React from 'react' import ReactDOM from 'react-dom' import './demo.css' import ContainInside from './examples/ContainInside' +import ContainOutside from './examples/ContainOutside' import Focal from './examples/Focal' import Standard from './examples/Standard' import SVG from './examples/SVG' @@ -24,6 +25,7 @@ function Demos() { + ) }