A Custom Element that does pinch-to-zoom, pan, and mouse-wheel zoom in/out
Demo: https://ianbellomy.github.io/Zoomy/deploy/
Use:
<script type="module" src="ZoomPanel.js"></script>
<zoom-panel style="touch-action:none">
<!-- stuff you want to manipulate -->
</zoom-panel>Notes:
- Uses PointerEvents.
- The contents are not constrained to the viewing area.
- Doesn't do tossing/flicking.
- If user leaves image zoomed out / scaled down, default behavior is to recenter and zoom to 1x.
- No dependencies.
Warning:
- If children or parent elements of zoom-panel capture
pointerupevents, the gesture tracking can break! If you've got ways of making the pointerID caching/tracking more bullet proof, I'm all ears, but for now, I can't guarantee this thing will behave entirely independently of what you put in it or what you put it in. As such, I recommend finding some way to sneak inzoomPanel.clearZoom()where it make sense; this will clear the pointer cache an unstick a gesture that won't quit because a pointer up was swallowed somewhere. (I've run into a particular headache when polyfilled pointer events don't properly pass up through a shadowdom leaving the zoom-panel still trying to track a pointerID that's never coming back. BARF!)
clearZoom()
Animate the content back to its default position and scale; reset the pointer tracking cache. I recommend providing some way for a user to trigger this. (See warning.)
pinchTo(scale:number,atX:number,atY:number,animate=false,center=false)
Perform a fake pinch such that the final scale is scale, and X/Y are based on scale of 1...
scaleThe scale to end up at, where 1 is 100%.atXThe x coordinate in panel at initial scale 1.atYThe x coordinate in panel at initial scale 1.animateShould the change be animated? Default isfalse.centerMove the content so that theoriginXandoriginYare in the middle of the zoom-panel element. Default isfalse.
doPinch(withScale:number,atX:number,atY:number,animate=false,center=false)
Perform a fake pinch on the transformed panel.
Repeat calls with the same values do not produce the same visual result.
Calls to this while gesturing are ignored.
withScaleThe final 'scale' of the fake pinch.originXThe x coordinate within the zoom-panel.originYThe x coordinate within the zoom-panel.animateShould the change be animated? Default isfalse.centerMove the content so that theoriginXandoriginYare in the middle of the zoom-panel element. Default isfalse.
Zoom-Panel emits the following custom events:
manipulationStartwhen a pan or pinch starts while there was no gesture, e.g. putting a second finger down while panning triggerspinchStartbut notmanipulationStart.panStartpanEndpinchStartpinchEndmanipulationEndwhen some gesture ends without switching to a different gesture, e.g. putting a second finger down triggerspanEndbut notmanipulationEnd.zoomDidClearwhen the animation initiated by clearZoom() completes.