【canvas】canvas绘制园区地图2

993 阅读1分钟

事件区分

pc端:

  • onmousedown
  • onmousemove
  • onmouseup
  • onmousewheel

mobile端:

  • ontouchstart
  • ontouchmove
  • ontouchend
  • 没有wheel函数,要通过touch的手指数目和趋势去做区分

代码

项目集合成vue框架中了


<template>
  <div class="box">
    <canvas ref="mapCanvas" :width="canvasWidth" :height="canvasHeight" style="border: red solid 1px; margin: 10px" />
    <div style="color: #fff; font-size: 22px;text-align:left">其他信息:{{ posStr }}</div>
  </div>
</template>

<script>
export default {
  name: 'Map',
  data() {
    return {
      canvasWidth: document.body.clientWidth - 20, // 画布大小
      canvasHeight: document.body.clientHeight - 200,
      myCanvas: null,
      ctx: null,

      imgX: -300, // 图片在画布中渲染的起点x坐标
      imgY: -50,
      MINIMUM_SCALE: 0.2,
      imgScale: 0.6, // 图片启示的缩放大小
      extraImg: { url: require('../../assets/map.png') },
      loadImgObj: null,

      img: null,
      flag: false,
      pos: {},
      posl: {},

      flagPC: true,
      posStr: ''
    }
  },
  watch: {

  },
  mounted() {
    this.flagPC = this.IsPC()
    this.myCanvas = this.$refs.mapCanvas
    this.ctx = this.myCanvas.getContext('2d')
    this.loadImg()
    this.canvasEventsInit()

    // 定位
    if (navigator.geolocation) {
      navigator.geolocation.watchPosition((position) => {
        var lat = position.coords.latitude
        var lng = position.coords.longitude
        this.posStr = '维度:' + lat + ', 经度:' + lng
      })
    }
  },
  destroyed() {

  },
  methods: {
    loadImg() {
      this.img = new Image()
      this.img.src = this.extraImg.url
      const that = this
      this.img.onload = function() {
        that.drawImage()
      }
    },

    drawImage() {
      const ctx = this.ctx
      ctx.clearRect(0, 0, this.myCanvas.width, this.myCanvas.height)
      ctx.drawImage(
        this.img, // 规定要使用的图像、画布或视频。
        0, 0, // 开始剪切的 x 坐标位置。
        this.img.width, this.img.height, // 被剪切图像的高度。
        this.imgX, this.imgY, // 在画布上放置图像的 x 、y坐标位置。
        this.img.width * this.imgScale, this.img.height * this.imgScale // 要使用的图像的宽度、高度
      )
      // 放置中心点
      ctx.beginPath()
      ctx.arc(this.canvasWidth / 2 - 20, this.canvasHeight / 2 - 20, 20, Math.PI * 2, 0, true)
      ctx.fillStyle = 'green'
      ctx.fill()
      ctx.fillStyle = '#fff' // 设置填充颜色为紫色
      ctx.font = '20px "微软雅黑"' // 设置字体
      ctx.textBaseline = 'middle' // 设置字体底线对齐绘制基线
      ctx.textAlign = 'center'
      ctx.fillText('我', this.canvasWidth / 2 - 20, this.canvasHeight / 2 - 20)
      ctx.closePath()
    },

    canvasEventsInit() {
      // eslint-disable-next-line no-unused-vars
      let pageX, pageY, initX, initY
      var start = []
      const canvas = this.myCanvas
      const that = this
      if (this.flagPC) {
        // PC
        // 使用mouse事件
      } else {
        // Phone
        canvas.ontouchstart = function(event) {
          that.flag = true
          if (event.touches && event.touches.length < 2) {
            const touch = event.touches[0]
            that.pos = that.windowToCanvas(touch.clientX, touch.clientY) // 坐标转换,将窗口坐标转换成canvas的坐标
          } else {
            const touches = event.touches
            // 手指按下时的手指所在的X,Y坐标
            pageX = touches[0].pageX
            pageY = touches[0].pageY
            // 初始位置的X,Y 坐标
            initX = event.target.offsetLeft
            initY = event.target.offsetTop
            // 记录初始 一组数据 作为缩放使用
            if (touches.length >= 2) { // 判断是否有两个点在屏幕上
              start = touches // 得到第一组两个点
            }
          }
        }
        canvas.ontouchmove = function(evt) {
          if (that.flag) {
            if (evt.touches && evt.touches.length < 2) { // 移动
              // console.log(evt)
              const touch = evt.touches[0]
              that.posl = that.windowToCanvas(touch.clientX, touch.clientY)
              var x = that.posl.x - that.pos.x; var y = that.posl.y - that.pos.y
              that.imgX += x
              that.imgY += y
              that.pos = JSON.parse(JSON.stringify(that.posl))
            } else { // 缩放
              event.preventDefault() // 禁止缩放
              const touches = evt.touches
              // 2 根 手指执行 目标元素放大操作
              // 得到第二组两个点
              var now = touches
              var pos = that.windowToCanvas(now[0].clientX, now[0].clientY)
              var newPos = {
                x: ((pos.x - that.imgX) / that.imgScale).toFixed(2),
                y: ((pos.y - that.imgY) / that.imgScale).toFixed(2)
              }
              // 当前距离变小, getDistance 是勾股定理的一个方法
              if (that.getDistance(now[0], now[1]) < that.getDistance(start[0], start[1])) {
                // 缩小
                that.imgScale -= 0.03
                if (that.imgScale < that.MINIMUM_SCALE) { // 最小缩放1
                  that.imgScale = that.MINIMUM_SCALE
                }
                that.imgX = (1 - that.imgScale) * newPos.x + (pos.x - newPos.x)
                that.imgY = (1 - that.imgScale) * newPos.y + (pos.y - newPos.y)
                // console.log(that.imgX,that.imgY);
              } else if (that.getDistance(now[0], now[1]) > that.getDistance(start[0], start[1])) {
                // 放大
                if (that.imgScale < 1) {
                  that.imgScale += 0.03
                  that.imgX = (1 - that.imgScale) * newPos.x + (pos.x - newPos.x)
                  that.imgY = (1 - that.imgScale) * newPos.y + (pos.y - newPos.y)
                }
              }
              start = now
            }
            that.drawImage() // 重新绘制图片
          }
        }
        canvas.ontouchend = function() {
          that.flag = false
        }
      }
    },

    /* 坐标转换*/
    windowToCanvas(x, y) {
      var box = this.myCanvas.getBoundingClientRect() // 这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离
      return {
        x: x - box.left - (box.width - this.myCanvas.width) / 2,
        y: y - box.top - (box.height - this.myCanvas.height) / 2
      }
    },

    // 缩放 勾股定理方法-求两点之间的距离
    getDistance(p1, p2) {
      var x = p2.pageX - p1.pageX
      var y = p2.pageY - p1.pageY
      return Math.sqrt((x * x) + (y * y))
    },

    IsPC() {
      var userAgentInfo = navigator.userAgent
      var Agents = ['Android', 'iPhone',
        'SymbianOS', 'Windows Phone',
        'iPad', 'iPod']
      var flag = true
      for (var v = 0; v < Agents.length; v++) {
        if (userAgentInfo.indexOf(Agents[v]) > 0) {
          flag = false
          break
        }
      }
      return flag
    }
  }
}
</script>

<style scoped>
* {
  font-size: 0;
  touch-action: pan-y;
}
.box {
  width: 100%;
  height: 100vh;
  overflow: hidden;
  text-align: center;
}
</style>

效果

2741627635470_.pic.jpg

2751627635472_.pic.jpg