vue2使用svg

vue使用svg在图片上进行各种绘制 

<template>
  <div class="outer" ref="outerRef">
    <div class="inner" ref="innerRef" :style="innerStyle">
      <img ref="imgRef" :src="mapUrl" alt="地图加载中" @load="imageLoad" />
      <svg ref="svgRef" :style="svgStyle">
        <image
          :href="robotPosition.url"
          :width="robotPosition.width"
          :height="robotPosition.height"
          :x="robotPosition.x"
          :y="robotPosition.y"
          :style="{
            // transform: robotPosition.transform,
            // transformOrigin: robotPosition.transformOrigin,
          }"
        />

        <text x="100" y="100" fill="red">1231</text>

        <g>
          <circle
            v-for="point in mapPointList"
            :key="point.id"
            :cx="point.x"
            :cy="point.y"
            r="4"
            fill="red"
          />
        </g>
      </svg>
    </div>
  </div>
</template>

<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  data() {
    return {
      mapUrl:
        "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg",
      robotPosition: {
        // x: 449,
        // y: 132,
        // x: 116,
        // y: 87,
        x: 0,
        y: 0,
        url: require("@/assets/images/robot.png"),
        // width: 16,
        // height: 16,
        width: 4.8,
        height: 4.8,
        transform: "rotate(33deg)", // 机器人朝向角度
        transformOrigin: "center center",
      },
      mapPointList: [
        {
          id: "1",
          x: 100,
          y: 100,
        },
        {
          id: "2",
          x: 200,
          y: 200,
        },
      ],
      imgoffsetX: 0,
      imgoffsetY: 0,
      scale: 1,
      svgInfo: {
        imageNaturalWidth: 1,
        imageNaturalHeight: 1,
        imageWidth: 1,
        imageHeight: 1,
        svgWidth: 1,
        svgHeight: 1,
        offsetX: 1,
        offsetY: 1,
        svgRate: 1,
        scale: 1.5,
      },
    };
  },
  mounted() {
    let aa = true;
    let a = [];
    this.$refs.outerRef.addEventListener("mousedown", (e) => {
      e.stopPropagation();
      e.preventDefault();
      console.log(e);
      aa = false;
      a.x = e.clientX;
      a.y = e.clientY;
    });

    this.$refs.outerRef.addEventListener("mousemove", (e) => {
      if (!aa) {
        let x = e.clientX - a.x;
        let y = e.clientY - a.y;
        this.imgoffsetX += x;
        this.imgoffsetY += y;
        a.x = e.clientX;
        a.y = e.clientY;
      }
    });
    this.$refs.outerRef.addEventListener("mouseup", (e) => {
      aa = true;
      //   console.log(e);
    });
    this.$refs.outerRef.addEventListener("mousewheel", (e) => {
      if (e) {
        if (e.wheelDelta > 0) {
          console.log("向上滚动");
          this.zoomIn();
          this.scale += 0.1;
        }

        if (e.wheelDelta < 0) {
          console.log("向xia滚动");
          this.zoomOut();

          this.scale -= 0.1;
        }
      }
    });

    // 移动端
    let isTouch = false; //是否为单触点
    let isDoubleTouch = false; //是否为多触点
    let start = []; //存放触点坐标
    this.$refs.innerRef.addEventListener("touchstart", (e) => {
      console.log(e);
      aa = false;
      if (e.touches.length >= 2) {
        //判断是否有两个点在屏幕上
        start = e.touches; //得到第一组两个点
        isDoubleTouch = true;
      } else {
        isTouch = true;
        a.x = e.touches[0].clientX;
        a.y = e.touches[0].clientY;
      }
    });

    this.$refs.innerRef.addEventListener("touchmove", (e) => {
      if (!aa) {
        if (e.touches.length >= 2 && isDoubleTouch) {
          //判断是否有两个点在屏幕上
          let now = e.touches; //得到第二组两个点
          let scale =
            getDistance(now[0], now[1]) / getDistance(start[0], start[1]); //得到缩放比例
          this.scale += scale;
        } else if (isTouch) {
          let x = e.touches[0].clientX - a.x;
          let y = e.touches[0].clientY - a.y;
          that.imgoffsetX += x;
          that.imgoffsetY += y;
          a.x = e.touches[0].clientX;
          a.y = e.touches[0].clientY;
        }
      }
    });
    this.$refs.innerRef.addEventListener("touchend", (e) => {
      aa = true;
      //   console.log(e);
      if (isDoubleTouch) {
        zoomKey = false;
        isDoubleTouch = false;
      } else if (isTouch) {
        isTouch = false;
      }
    });
  },
  computed: {
    svgStyle() {
      return {
        width: this.svgInfo.svgWidth + "px",
        height: this.svgInfo.svgHeight + "px",
        left: this.svgInfo.offsetX + "px",
        top: this.svgInfo.offsetY + "px",
      };
    },
    innerStyle() {
      return {
        left: this.imgoffsetX + "px",
        top: this.imgoffsetY + "px",
        transform: `scale(${this.scale})`,
      };
    },
  },

  methods: {
    zoomIn() {
      this.svgInfo.scale += 0.1;
    },
    zoomOut() {
      this.svgInfo.scale -= 0.1;
    },
    moveRight() {
      this.svgInfo.offsetX += 10;
    },
    moveLeft() {
      this.svgInfo.offsetX -= 10;
    },
    moveUp() {
      this.svgInfo.offsetY -= 10;
    },
    moveDown() {
      this.svgInfo.offsetY += 10;
    },
    imageLoad() {
      const imgRef = this.$refs.imgRef;
      this.svgInfo = {
        imageNaturalWidth: imgRef.naturalWidth,
        imageNaturalHeight: imgRef.naturalHeight,

        imageWidth: imgRef.clientWidth,
        imageHeight: imgRef.clientHeight,

        svgWidth: imgRef.clientWidth,
        svgHeight: imgRef.clientHeight,

        offsetX: 0,
        offsetY: 0,

        svgRate: 1,
      };

      let svgRate = this.svgInfo.imageWidth / this.svgInfo.imageHeight;
      let imageNaturalRate =
        this.svgInfo.imageNaturalWidth / this.svgInfo.imageNaturalHeight;
      console.log(svgRate, imageNaturalRate);
      if (svgRate > imageNaturalRate) {
        this.svgInfo.svgRate =
          this.svgInfo.imageHeight / this.svgInfo.imageNaturalHeight;
        this.svgInfo.svgHeight = this.svgInfo.imageHeight;
        this.svgInfo.svgWidth = this.svgInfo.imageHeight * imageNaturalRate;
      } else {
        this.svgInfo.svgRate =
          this.svgInfo.imageWidth / this.svgInfo.imageNaturalWidth;
        this.svgInfo.svgWidth = this.svgInfo.imageWidth;
        this.svgInfo.svgHeight = this.svgInfo.imageWidth / imageNaturalRate;
      }

      this.svgInfo.offsetX =
        (this.svgInfo.imageWidth - this.svgInfo.svgWidth) / 2;
      this.svgInfo.offsetY =
        (this.svgInfo.imageHeight - this.svgInfo.svgHeight) / 2;
      this.robotPosition.width = 16 * this.svgInfo.svgRate;
      this.robotPosition.height = 16 * this.svgInfo.svgRate;
      this.robotPosition.x = this.svgInfo.svgRate * 680;
      this.robotPosition.y =
        this.svgInfo.svgHeight - this.svgInfo.svgRate * 167;
    },
  },
};
</script>

<style lang="scss" scoped>
.outer {
  width: 100%;
  height: 100%;
  overflow: hidden;

  position: relative;

  padding: 50px;
  box-sizing: border-box;

  .inner {
    width: 100%;
    height: 100%;

    position: relative;

    img {
      width: 100%;
      height: 100%;
      object-fit: contain;
      position: absolute;
      left: 0;
      top: 0;
    }

    svg {
      position: absolute;

      width: 100%;
      height: 100%;
    }
  }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值