framer-motion
Version:
A simple and powerful JavaScript animation library
63 lines (60 loc) • 2.31 kB
JavaScript
import { Feature, addPinchListeners } from 'motion-dom';
const valueKeys = ["scale", "rotate", "x", "y"];
class PinchGesture extends Feature {
constructor() {
super(...arguments);
this.touchAction = "";
}
mount() {
const { current } = this.node;
if (!current)
return;
this.touchAction = current.style.touchAction;
this.update();
/**
* The latest enabled options. addPinchListeners reads them before
* each step of a gesture, so they're current when a callback runs,
* and a pinch disabled mid-way still calls its `onEnd`.
*/
let options = {};
/**
* Call the prop's `onStart`, `onMove` or `onEnd`, so each can
* change mid-gesture.
*/
const call = (key) => (event, info) => options[key]?.(event, info);
this.unmount = addPinchListeners(current, () => valueKeys.map((key) => this.node.getValue(key, key === "scale" ? 1 : 0)), () => {
const { pinch } = this.node.getProps();
return pinch && (options = pinch === true ? {} : pinch);
}, (_element, event, info) => {
const setActive = (isActive) => this.node.animationState?.setActive("whilePinch", isActive);
setActive(true);
call("onStart")(event, info);
return {
onPinch: call("onMove"),
onComplete: (event, info) => {
setActive(false);
call("onEnd")(event, info);
},
};
});
}
/**
* Stop touches panning or zooming the page while pinch is on, unless
* `style` sets a `touchAction` (like "pan-y" for a list that scrolls
* with one finger). Set here rather than when rendering, so the default
* bundle doesn't pay for it, and on every update, as React rewrites it
* when drag's axis changes.
*/
update() {
const style = this.node.current?.style;
if (style) {
const { pinch, style: props } = this.node.getProps();
style.touchAction = pinch
? props?.touchAction || "none"
: this.touchAction;
}
}
unmount() { }
}
export { PinchGesture };
//# sourceMappingURL=pinch.mjs.map