zoombo
v1.1.0
Published
Element pinch zoom and pan behaviour handler - supporting touch, mouse and trackpad events.
Readme
Zoombo
Element pinch zoom and pan behaviour handler - supporting touch, mouse and trackpad events.
yarn add --dev zoomboContents:
Basic usage:
import Zoombo from 'zoombo';
const figureElm = document.querySelector('.figure');
const myZoombo = Zoombo({
refElm: figureElm,
opts: {
maxZoom: 10, // other options
},
onStart: (state) => {
figureElm.classList.add('figure--is-dragging');
},
onChange: (state) => {
figureElm.style.transform = state.cssTransform;
// See chapter on zoombo state properties below...
},
onEnd: (state) => {
figureElm.classList.remove('figure--is-dragging');
},
});
myZoombo.start(); // bind DOM eventsThe returned instance object has a few useful methods...
// Perform actions
myZoombo.actions.panTo(0.25, 0.6);
myZoombo.actions.zoomIn();
// etc...
// Inspect the current zoombo state...
const currentState = myZoombo.getState();
// Modify the options
myZoombo.updateOpts({ minZoom: 1 });
// Enable/Disable
myZoombo.stop(); // unbind DOM events
console.log(myZoombo.isActive()); // false
myZoombo.start(); // resume (re-bind events)
console.log(myZoombo.isActive()); // true
myZoombo.actions.reset();Options (w/ defaults)
const options = {
initialZoom: 1,
initialX: 0.5,
initialY: 0.5,
maxZoom: 4,
minZoom: 1,
marginX: 0,
marginY: 0,
zoomStep: 2,
panStep: 0.5,
dragThreshold: 7, // px
pinchThreshold: 30, // px
oneFingerPan: false,
};The values panStep, initialX and initialY are numbers from 0 to 1
representing proportion of the provided reference element's
offsetWidth/offsetHeight values.
While marginX and marginY are any positive number representing proportion
of the provided reference element's offsetWidth/offsetHeight before
zooming.
React Component
The optional React helper comes in two flavours:
Render-props version
import React from 'react';
import Zoombo from 'zoombo/react'; // esm version
// import Zoombo from 'zoombo/cjs/react'; // CommonJS version
const logState = (zoomboState) => {
console.log('zoombo', zoomboState);
};
const MyFigureComponent = (props) => (
<Zoombo
maxZoom={4}
initialZoom={2}
onStart={logState}
onChange={logState}
onEnd={logState}
disabled={false}
>
{(zoomboRef, zoombo /* , zoomboActions */) => (
<div
className={
'figure' + (zoombo.isDragging ? ' figure--is-dragging' : '')
}
ref={zoomboRef}
style={{ transform: zoombo.cssTransform }}
>
<img src={props.src} alt={props.altText} />
</div>
)}
</Zoombo>
);
export default MyFigureComponent;The <Zoombo/> component's props are passed directly on to the underlying
Zoombo() function – with the notable exception of disabled which acts as a
signal for activating the .start() and .stop() methods.
HOC version
import React from 'react';
import Zoombo from 'zoombo/react'; // esm version
// import Zoombo from 'zoombo/cjs/react'; // CommonJS version
const logState = (zoomboState) => {
console.log('zoombo', zoomboState);
};
const MyFigureComponent = (props) => {
const { zoomboRef, zoombo /* , zoomboActions */ } = props;
return (
<div
className={'figure' + (zoombo.isDragging ? ' figure--is-dragging' : '')}
ref={zoomboRef}
style={{ transform: zoombo.cssTransform }}
>
<img src={props.src} alt={props.altText} />
</div>
);
};
export default Zoombo.withZoombo(MyFigureComponent, {
maxZoom: 4,
initialZoom: 2,
onStart: logState,
onChange: logState,
onEnd: logState,
disabled: false,
});The second argument to the Zoombo.withZoombo HOC can also be a function:
const propsToZoomboOpts = (props) => ({
maxZoom: 4,
initialZoom: 2,
onStart: logState,
onChange: logState,
onEnd: logState,
disabled: props.disabled,
});
export default Zoombo.withZoombo(MyFigureComponent, propsToZoomboOpts);Zoombo state
The Zoombo state exposed to the onStart, onChange and onEnd callbacks,
includes these basic props:
zoom: number- The current zoom factorx: number,y: number- The current focal/center points (bounded byzoom,opts.marginXandopts.marginY)isDragging: boolean– Flag indicating if the user is currently dragging/pinching/etc.
The state also includes some precalculated CSS-friendly props:
cssSize: number– Percentage for use forwidthandheight(100 * state.zoom)cssTop: number,cssLeft: number– Percentage for CSS positioning (-cssSize * state.{x|y} + 50)cssTranslateX: number,cssTranslateY: number– Percentage for translation offsets (-100 * state.{x|y} + 50)cssTransform: string– Ready to use transformation string in the form of:scale(${state.zoom}) translate3d(${cssTranslateX}%, ${cssTranslateY}%, 0),
Actions
A Zoombo instance has the following .actions that can be used to hook up
UI buttons or add scripted behaviour to the zoombo element
panN(numSteps),panE(numSteps),panS(numSteps),panW(numSteps)Pans towards the given direction (N,S,E,W) by a factor ofnumSteps * opts.panStep / currentZoompanBy(xFactor, yFactor)Changes the pan by the given X and Y factors (scaled by the current zoom level).panTo(x?, y?)Pans directly to the givenxandycoordinates, where(0,0)is top-left and(1,1)is bottom-right.zoomIn(numSteps, x?, y?)Zooms in by a factor ofnumSteps * opts.zoomStep / currentZoomtowards an optional newx,ycenterpointzoomOut(numSteps, x?, y?)– Zooms out by a factor ofnumSteps * opts.zoomStep / currentZoomtowards an optional newx,ycenterpointzoomBy(factor, x?, y?)– Changes the zoom-level by the givenfactortowards an optional newx,ycenterpoint.zoomTo(zoom, x?, y?)Zooms directly to the givenzoomlevel and (optionally) pan toxandyreset()Resets the zoom and pan back to initial values.
API
...TODO...
