UNPKG

svg-zoom-drag-vue-directives

Version:

Provide two Vue custom directives that are compatible with Vue 2 and Vue 3.

79 lines (76 loc) 3.9 kB
'use strict'; // Control the zoom in and out of an SVG image by setting the viewbox attribute of the SVG element. The third parameter of the viewbox controls the horizontal size, while the fourth parameter sets the vertical size. function svgWheel(app) { app.directive("svgWheel", (el) => { if (el) { el.onwheel = (e) => { // Because the SVG is rendered using v-html, the child element of the bound DOM is the SVG element. const svgDom = el.firstChild; const viewBox = svgDom.getAttribute("viewBox"); const [x, y, width, height] = viewBox.split(/\s+/).map(parseFloat); // event.wheelDelta has been deprecated, use event.deltaY instead. // event.deltaY returns a positive value when scrolling downwards and a negative value when scrolling upwards. Otherwise, it is 0. event.wheelDelta is the opposite. const scaleDelta = e.deltaY > 0 ? 0.9 : 1.1; // Zoom scale. const newWidth = width * scaleDelta; const newHeight = height * scaleDelta; // Calculate the centering offset. const dx = (width - newWidth) / 2; const dy = (height - newHeight) / 2; const newViewBox = `${x + dx} ${y + dy} ${newWidth} ${newHeight}`; svgDom.setAttribute("viewBox", newViewBox); }; } }); } // Control the drag of an SVG image by setting the "viewBox" attribute of the SVG element. The first parameter of "viewBox" controls the left-right position, and the second parameter sets the up-down position. function svgDrag(app) { app.directive("svgDrag", (el) => { let clientX = 0; // The last x-axis position of the mouse let clientY = 0; // The last y-axis position of the mouse let debounce = true; // Throttling is necessary, otherwise the dragging effect will appear jerky let isStartMoveSvg = false; // Whether to start dragging let ratio = 1; // The ratio of drag speed to size let sgvDom; // The SVG element let viewBox; // The "viewBox" attribute of the SVG element let arrPoint; // The value of the "viewBox" attribute of the SVG element // Mouse down means start moving el.onmousedown = () => { isStartMoveSvg = true; const width = el.getBoundingClientRect().width; // Because the SVG is rendered using "v-html", the child element of the bound command DOM is the SVG element sgvDom = el.firstChild; viewBox = sgvDom.getAttribute("viewBox"); arrPoint = viewBox.split(/\s+/).map(parseFloat); // Dynamically adjust the drag speed based on the size, otherwise it becomes harder to drag as the SVG becomes smaller ratio = arrPoint[2] / width; if (ratio < 1) ratio = 1; }; // Mouse up means end moving el.onmouseup = () => { isStartMoveSvg = false; clientX = 0; clientY = 0; }; // Dynamically set "viewBox" while moving el.onmousemove = (e) => { if (debounce) { debounce = false; if (isStartMoveSvg) { if (clientX !== 0 && clientY !== 0) { arrPoint[0] = arrPoint[0] - (e.clientX - clientX) * ratio; arrPoint[1] = arrPoint[1] - (e.clientY - clientY) * ratio; sgvDom.setAttribute("viewBox", arrPoint.join(" ")); } clientX = e.clientX; clientY = e.clientY; } setTimeout(() => { debounce = true; }, 50); } }; }); } exports.svgDrag = svgDrag; exports.svgWheel = svgWheel;