Skip to content

Commit

Permalink
feat(constrain): add contain:true option (timmywil#598)
Browse files Browse the repository at this point in the history
  • Loading branch information
nashiko committed Aug 1, 2022
1 parent 8a8805d commit 6d4748a
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 20 deletions.
65 changes: 65 additions & 0 deletions demo/examples/ContainTrue.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import Panzoom, { PanzoomObject } from '../../src/panzoom'
import React, { useEffect, useRef } from 'react'

import Code from '../Code'
import Demo from '../Demo'

const code = <Code>{`Panzoom(elem, { contain: true })`}</Code>

export default function ContainTrue() {
const elem = useRef<HTMLDivElement>(null)
let panzoom: PanzoomObject
useEffect(() => {
panzoom = Panzoom(elem.current, { contain: true, startScale: 1.3 })
panzoom.pan(10, 10, { relative: true })
const parent = elem.current.parentElement
parent.addEventListener('wheel', function (event) {
if (!event.shiftKey) {
return
}
panzoom.zoomWithWheel(event)
})
}, [])
return (
<Demo title="Containment within the parent" code={code}>
<div className="buttons">
<label>Try me: </label>
<button
onClick={() => {
panzoom.zoomIn()
}}
>
Zoom in
</button>
<button
onClick={() => {
panzoom.zoomOut()
}}
>
Zoom out
</button>
<button
onClick={() => {
panzoom.reset()
}}
>
Reset
</button>
</div>
<div className="panzoom-parent">
<div
className="panzoom"
ref={elem}
style={{
background: '#000',
width: '400px',
border: '2px dotted #ff0',
margin: '0 auto'
}}
>
<img style={{ width: '100%', height: '100%' }} src="awesome_tiger.svg" />
</div>
</div>
</Demo>
)
}
2 changes: 2 additions & 0 deletions demo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import './global-panzoom'

import ContainInside from './examples/ContainInside'
import ContainOutside from './examples/ContainOutside'
import ContainTrue from './examples/ContainTrue'
import DisabledYAxis from './examples/DisabledYAxis'
import Exclude from './examples/Exclude'
import Focal from './examples/Focal'
Expand Down Expand Up @@ -33,6 +34,7 @@ function Demos() {
<SVG />
<ContainInside />
<ContainOutside />
<ContainTrue />
<Exclude />
<DisabledYAxis />
<Rotate />
Expand Down
75 changes: 56 additions & 19 deletions src/panzoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ function Panzoom(
panOptions?: PanOptions
) {
const opts = { ...options, ...panOptions }
let contain = opts.contain
const result = { x, y, opts }
if (!opts.force && (opts.disablePan || (opts.panOnlyWhenZoomed && scale === opts.startScale))) {
return result
Expand All @@ -194,7 +195,7 @@ function Panzoom(
result.y = (opts.relative ? y : 0) + toY
}

if (opts.contain) {
if (contain) {
const dims = getDimensions(elem)
const realWidth = dims.elem.width / scale
const realHeight = dims.elem.height / scale
Expand All @@ -203,7 +204,13 @@ function Panzoom(
const diffHorizontal = (scaledWidth - realWidth) / 2
const diffVertical = (scaledHeight - realHeight) / 2

if (opts.contain === 'inside') {
if (contain === true) {
contain =
scaledWidth > dims.parent.width || scaledHeight > dims.parent.height
? 'outside'
: 'inside'
}
if (contain === 'inside') {
const minX = (-dims.elem.margin.left - dims.parent.padding.left + diffHorizontal) / toScale
const maxX =
(dims.parent.width -
Expand All @@ -226,24 +233,54 @@ function Panzoom(
diffVertical) /
toScale
result.y = Math.max(Math.min(result.y, maxY), minY)
} else if (opts.contain === 'outside') {
const minX =
(-(scaledWidth - dims.parent.width) -
dims.parent.padding.left -
dims.parent.border.left -
dims.parent.border.right +
diffHorizontal) /
toScale
const maxX = (diffHorizontal - dims.parent.padding.left) / toScale
} else if (contain === 'outside') {
let minX, maxX
if (scaledWidth - dims.parent.width < 0) {
minX = (-dims.elem.margin.left - dims.parent.padding.left + diffHorizontal) / toScale
maxX =
(dims.parent.width -
scaledWidth -
dims.parent.padding.left -
dims.elem.margin.left -
dims.parent.border.left -
dims.parent.border.right +
diffHorizontal) /
toScale
} else {
minX =
(-(scaledWidth - dims.parent.width) -
dims.parent.padding.left -
dims.elem.margin.left -
dims.parent.border.left -
dims.parent.border.right +
diffHorizontal) /
toScale
maxX = (diffHorizontal - dims.parent.padding.left - dims.elem.margin.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) /
toScale
const maxY = (diffVertical - dims.parent.padding.top) / toScale
let minY, maxY
if (scaledHeight - dims.parent.height < 0) {
minY = (-dims.elem.margin.top - dims.parent.padding.top + diffVertical) / toScale
maxY =
(dims.parent.height -
scaledHeight -
dims.parent.padding.top -
dims.elem.margin.top -
dims.parent.border.top -
dims.parent.border.bottom +
diffVertical) /
toScale
} else {
minY =
(-(scaledHeight - dims.parent.height) -
dims.parent.padding.top -
dims.elem.margin.top -
dims.parent.border.top -
dims.parent.border.bottom +
diffVertical) /
toScale
maxY = (diffVertical - dims.parent.padding.top - dims.elem.margin.top) / toScale
}
result.y = Math.max(Math.min(result.y, maxY), minY)
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,11 @@ export interface PanOnlyOptions {
* than its parent and cannot be panned
* to the inside. In other words, no
* empty space around the element will be shown.
* true: Automatically switches Inside or Outside.
*
* **Note**: the containment pan adjustment is not affected by the `disablePan` option.
*/
contain?: 'inside' | 'outside'
contain?: 'inside' | 'outside' | true
/** The cursor style to set on the panzoom element */
cursor?: string
/**
Expand Down

1 comment on commit 6d4748a

@shasabbir
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing solved zoomed element still getting out of div

Please sign in to comment.