相关文章推荐
潇洒的吐司  ·  X-MOL·  1 年前    · 
酒量大的小蝌蚪  ·  sql server - HOW CAN ...·  1 年前    · 
鬼畜的面包  ·  一维CNN - 简书·  1 年前    · 
  1. 基于svg viewbox属性居中进行放大缩小
  2. 基于svg viewbox属性进行平滑拖动

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
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");
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;

这样设计是为了搭配v-html

<div id="svg" v-html="svgString" v-svgWheel v-svgDrag></div>
                    https://zqy233.github.io/svg-zoom-drag-vue-demo/#/https://github.com/zqy233/svg-zoom-drag-vue-demo上方两个自定义指令已经发布为npm包,可以直接安装使用Vue2Vue3绑定两个命令到dom上注意点指令将绑定元素的第一个子元素当做 svg,所以请注意绑定的元素这样设计是为了搭配
首先我是需要一个SVG图的缩放和平移,svg图是自己做的,然后里面有自己做的动画以及其他时间,但是前几天客户说要改需求,说需要这个图实现SVG拖动缩放,
MD,我只是一个后端啊,好吧,后端和前端已经感觉没有区别了。
之前做SVG动画的时候,学习了一下svg的一些动画特效,国内的一个博客写的很好
超级强大的SVG
				
最经在做一个与SVG图片相关的功能,涉及到对该类图片的放大缩小拖动操作,就像地图一样的效果。原理不细说了,请看文章《How to Zoom and Pan with SVG》。在此讲一下具体怎么实现. 首先,要在svg文件添加,如果svg文件头部没有包含命名空间"xmlns:xlink="http://www.w3.org/1999/xlink",则需要加上该命名空间 然后,在svg文件中添
svg元素不会太多,否则会造成卡顿。 最近有个项目需要我帮一下前端,主要是使用d3绘制svg放在页面,其中有一个功能就是对绘制的svg进行拖动缩放,有点像地图。 这里我已经写好了一个方法来绘制svg function drawTopo(svg, data, x, y, svgA, radio)... 在web中对svg图形的操作,我使用svg.js库挺久的了,对svg图形的拖动缩放我一直用的衍生插件svg.panzoom.js svg.panzoom库对svg拖拽缩放实现是对viewBox的设置来进行缩放的,至于使用viewBox缩放拖拽的原理,建议各位百度了解一下,不细说了(以后有空可以讲解一下) 最近使用这个库拖拽svg发现了一个比较严重的性能问题(其实之前一个项目就发现了,不过当时没有这么卡顿且需求是只用同时预览一张图即可),对性能没有太大要求,便没有多管,现在这个项目是多tab页
简单使用transform: translate属性实现SVG拖拽移动与缩放JS代码load()函数鼠标按下事件释放加载在window的鼠标松开事件鼠标滑动事件滚轮滚动事件 HTML代码 <body onload="load()"> <div style="width:500px;height:500px;margin: auto;overflow: hidden;"> <svg id="svg" version="1.1" xmlns="http:/
闲来无事写了个地图控件,基于SVG。可以缩放,可拖动,可点击。SVG具有体积小,不失真的优点。而且由于保存的是路径信息,可以做到复杂图形的点击判断功能。还是很香的。 原理,SVG 意为可缩放矢量图形(Scalable Vector Graphics)。 SVG 使用 XML 格式定义图像。在xml中定义了路径,只需要将路径解析保存到path中。再绘制出来就行了。 svg地图的获取 使用如下地址(需要科学上网) Pixel Map 首页是这样的,支持世界上所有国家 下载中国地图