In the HTML, we need a parent/wrapper element which will act as the bounds for our draggable SVG element:
<div id="container" style="width: 800px; height: 400px;">
<svg id="svg"><!-- rest of the svg code --></svg>
</div>
Next, initialize the Draggable with GSAP:
import gsap from 'gsap';
import Draggable from 'gsap/Draggable';
const draggable = Draggable.create('#svg', {
type: 'x,y',
bounds: '#container',
inertia: true,
throwResistance: 300,
throwProps: true,
allowEventDefault: true,
})[0];
An important aspect to get it to be “smooth” and not display a blank viewBox when zooming in/out or resetting the zoom, is to also update the bounds of the SVG element while it’s zooming (onUpdate
):
function zoom() {
const zoomLevel = 2;
gsap.to('#svg',
{
scale: zoomLevel,
transformOrigin: 'center center',
onUpdate: () => {
draggable.applyBounds('#container');
draggable.update();
},
});
}
Full demo & working code available here: