Skip to content

Commit

Permalink
fix(constrain): always get new dimensions when constraining scale
Browse files Browse the repository at this point in the history
- also check for width and height of 0 to avoid NaN

Fixes gh-594
  • Loading branch information
timmywil committed Dec 20, 2021
1 parent 174cbb4 commit 834f7f6
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 26 deletions.
48 changes: 22 additions & 26 deletions src/panzoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,6 @@ function Panzoom(
parent.style.touchAction = opts.touchAction
elem.style.touchAction = opts.touchAction
}
if (
opts.hasOwnProperty('minScale') ||
opts.hasOwnProperty('maxScale') ||
opts.hasOwnProperty('contain')
) {
setMinMax()
}
}

let x = 0
Expand All @@ -146,7 +139,6 @@ function Panzoom(
// for accurate dimensions
// to constrain initial values
setTimeout(() => {
setMinMax()
pan(options.startX, options.startY, { animate: false, force: true })
})

Expand Down Expand Up @@ -179,23 +171,6 @@ 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,
Expand Down Expand Up @@ -286,7 +261,28 @@ function Panzoom(
if (!opts.force && opts.disableZoom) {
return result
}
result.scale = Math.min(Math.max(toScale, opts.minScale), opts.maxScale)

let minScale = options.minScale
let maxScale = options.maxScale

if (opts.contain) {
const dims = getDimensions(elem)
const elemWidth = dims.elem.width / scale
const elemHeight = dims.elem.height / scale
if (elemWidth > 1 && elemHeight > 1) {
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 elemScaledWidth = parentWidth / elemWidth
const elemScaledHeight = parentHeight / elemHeight
if (options.contain === 'inside') {
maxScale = Math.min(maxScale, elemScaledWidth, elemScaledHeight)
} else if (options.contain === 'outside') {
minScale = Math.max(minScale, elemScaledWidth, elemScaledHeight)
}
}
}

result.scale = Math.min(Math.max(toScale, minScale), maxScale)
return result
}

Expand Down
35 changes: 35 additions & 0 deletions test/unit/panzoom.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,41 @@ describe('Panzoom', () => {
assert.strictEqual(pan.y, 0)
document.body.removeChild(parent)
})
it("still works even after an element's dimensions change", async () => {
const parent = document.createElement('div')
const div = document.createElement('div')
div.style.width = '0'
div.style.height = '0'
parent.style.width = '100px'
parent.style.height = '100px'
parent.appendChild(div)
document.body.appendChild(parent)
const panzoom = Panzoom(div, { contain: 'outside' })
await skipFrame()
panzoom.zoom(2)
// Zoom needs to paint first
await skipFrame()
// Still sets scale regardless of it begin 0/0
const scale = panzoom.getScale()
assert.strictEqual(scale, 2)
// Set the pan and let it through
// without constraints, which means
// 50, 50 because the scale is 2.
panzoom.pan(100, 100)
await skipFrame()
let pan = panzoom.getPan()
assert.strictEqual(pan.x, 50)
assert.strictEqual(pan.y, 50)
div.style.width = '100px'
div.style.height = '100px'
panzoom.pan(100, 100)
await skipFrame()
// Now contrains to 25, 25
pan = panzoom.getPan()
assert.strictEqual(pan.x, 25)
assert.strictEqual(pan.y, 25)
document.body.removeChild(parent)
})
})
describe('reset', () => {
it('ignores disablePan, disableZoom, and panOnlyWhenZoomed', () => {
Expand Down

0 comments on commit 834f7f6

Please sign in to comment.