本文介绍: https://zqy233.github.io/svg–zoom–drag–vue–demo/#/https://github.com/zqy233/svg–zoom–drag–vue–demo上方两个自定义指令已经发布为npm包,可以直接安装使用Vue2Vue3绑定两个命令到dom上注意点指令将绑定元素的第一个子元素当做 svg,所以请注意绑定的元素这样设计是为了搭配
效果
demo
demo预览地址
https://zqy233.github.io/svg-zoom-drag-vue-demo/#/
demo完整代码地址
https://github.com/zqy233/svg-zoom-drag-vue-demo
定义自定义命令v-svgWheel
和v-svgDrag
import { Vue2, App } from "vue-demi";
/** create a `v-svgWheel` directive for a Vue app, allows the user to control the zoom in and out of an SVG image using the mouse wheel. */
export function svgWheel(app: typeof Vue2): void;
/** create a `v-svgWheel` directive for a Vue app, allows the user to control the zoom in and out of an SVG image using the mouse wheel. */
export function svgWheel(app: App<Element>): void;
// 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.
export function svgWheel(app: typeof Vue2 | App<Element>) {
app.directive("svgWheel", (el: HTMLElement) => {
if (el) {
el.onwheel = (e: WheelEvent) => {
// Because the SVG is rendered using v-html, the child element of the bound DOM is the SVG element.
const svgDom = el.firstChild as SVGSVGElement;
const viewBox = svgDom.getAttribute("viewBox") as string;
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);
};
}
});
}
/** create a `v-svgDrag` directive for a Vue app, allows the user to drag the SVG image by holding down the mouse and moving the cursor.
*/
export function svgDrag(app: typeof Vue2): void;
/** create a `v-svgDrag` directive for a Vue app, allows the user to drag the SVG image by holding down the mouse and moving the cursor.
*/
export function svgDrag(app: App<Element>): void;
// 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.
export function svgDrag(app: typeof Vue2 | App<Element>) {
app.directive("svgDrag", (el: HTMLElement) => {
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: SVGAElement; // The SVG element
let viewBox: string; // The "viewBox" attribute of the SVG element
let arrPoint: number[]; // 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 as SVGAElement;
viewBox = sgvDom.getAttribute("viewBox") as string;
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: MouseEvent) => {
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);
}
};
});
}
上方两个自定义指令已经发布为npm包,可以直接安装使用
npm i -s svg-zoom-drag-vue-directives
Vue2
import Vue from "vue";
import App from "./App.vue";
import { svgWheel, svgDrag } from "svg-zoom-drag-vue-directives";
svgWheel(Vue);
svgDrag(Vue);
new Vue({
render: (h) => h(App),
}).$mount("#app");
Vue3
import { createApp } from "vue";
import App from "./App.vue";
import { svgWheel, svgDrag } from "svg-zoom-drag-vue-directives";
const app = createApp(App);
svgWheel(app);
svgDrag(app);
app.mount("#app");
绑定两个命令到dom上
<template>
<div id="svg" v-html="svgString" v-svgWheel v-svgDrag></div>
</template>
<script setup lang="ts">
import { svgText } from "./svgText";
const svgString = ref("");
onMounted(() => {
svgString.value = svgText;
});
</script>
<style>
* {
margin: 0;
padding: 0;
}
#svg {
width: 100%;
height: 100vh;
overflow: hidden;
}
svg {
width: 100% !important;
height: 100% !important;
user-select: none;
}
</style>
注意点
指令将绑定元素的第一个子元素当做 svg,所以请注意绑定的元素
const svgDom = el.firstChild as SVGSVGElement;
<div id="svg" v-html="svgString" v-svgWheel v-svgDrag></div>
原文地址:https://blog.csdn.net/qq_42611074/article/details/125151650
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_38082.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。