diff --git a/demo/examples/ContainOutside.tsx b/demo/examples/ContainOutside.tsx index cc4955fb..6697cee8 100644 --- a/demo/examples/ContainOutside.tsx +++ b/demo/examples/ContainOutside.tsx @@ -1,17 +1,43 @@ import React, { useEffect, useRef } from 'react' -import Panzoom from '../../src/panzoom' + import Code from '../Code' import Demo from '../Demo' +import Panzoom from '../../src/panzoom' +import { PanzoomObject } from '../../src/types' const code = {`Panzoom(elem, { contain: 'outside', startScale: 1.5 })`} export default function ContainOutside() { const elem = useRef(null) + let panzoom: PanzoomObject useEffect(() => { - Panzoom(elem.current, { contain: 'outside', startScale: 1.5 }) + setTimeout(() => { + panzoom = Panzoom(elem.current, { contain: 'outside', startScale: 1.5 }) + }, 1000) }, []) return ( +
+ + + + +
{ + setMinMax() pan(options.startX, options.startY, { animate: false }) }) @@ -127,6 +135,23 @@ function Panzoom( return value } + function setMinMax() { + if (options.contain) { + const dims = getDimensions(elem) + const parentWidth = dims.parent.width - dims.parent.border.left - dims.parent.border.right + const parentHeight = dims.parent.height - dims.parent.border.top - dims.parent.border.bottom + const elemWidth = dims.elem.width / scale + const elemHeight = dims.elem.height / scale + const elemScaledWidth = parentWidth / elemWidth + const elemScaledHeight = parentHeight / elemHeight + if (options.contain === 'inside') { + options.maxScale = Math.min(elemScaledWidth, elemScaledHeight) + } else if (options.contain === 'outside') { + options.minScale = Math.max(elemScaledWidth, elemScaledHeight) + } + } + } + function constrainXY(toX: number | string, toY: number | string, panOptions?: PanOptions) { const opts = { ...options, ...panOptions } const result = { x, y, opts } @@ -235,8 +260,12 @@ function Panzoom( x = panResult.x y = panResult.y } - scale = toScale + if (!opts.focal) { + const panResult = constrainXY(x, y, { relative: false }) + x = panResult.x + y = panResult.y + } return setTransformWithEvent('panzoomzoom', opts) } diff --git a/test/unit/panzoom.test.ts b/test/unit/panzoom.test.ts index fa624e57..5da048fb 100644 --- a/test/unit/panzoom.test.ts +++ b/test/unit/panzoom.test.ts @@ -85,6 +85,19 @@ describe('Panzoom', () => { assert.equal(div.style.cursor, 'default', 'Cursor style changes when setting the cursor option') document.body.removeChild(div) }) + describe('contain option', () => { + it(': outside sets the pan on the zoom to maintain containment', () => { + const div = document.createElement('div') + document.body.appendChild(div) + const panzoom = Panzoom(div, { contain: 'outside' }) + panzoom.zoom(2) + panzoom.pan(100, 100) + panzoom.zoom(1) + const pan = panzoom.getPan() + assert.equal(pan.x, 0) + assert.equal(pan.y, 0) + }) + }) describe('force option', () => { it('ignores disablePan', () => { const div = document.createElement('div')