vue 移动端 canvas 触摸板

需求

通过canvas来实现触摸板来写下一些题目的解题步骤,然后使用设备是手机跟pad

代码

vue

<template>
  <canvas id="canvas" @touchstart="touchstart" @touchend="touchend" @touchmove="touchmove"></canvas>
</template>

js

export default {
  data() {
    return {
      ctx: '',
      point: {
        x: 0,
        y: 0
      }
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    /**
     * @description: canvas 初始化
     * @param {type}
     * @return:
     */
    init() {
      const canvas = document.getElementById('canvas')
      this.ctx = canvas.getContext('2d')
      this.ctx.strokeStyle = '#474E60'
      this.ctx.lineWidth = 1
    },
    /**
     * @description: 获取相对坐标
     * @param {type}
     * @return:
     */
    absolutePoint(event) {
      const touch = event.targetTouches[0]
      const canvas = document.getElementById('canvas')
      const react = canvas.getBoundingClientRect()
      this.point = { x: touch.pageX - react.left, y: touch.pageY - react.top }
    },
    /**
     * @description: 绘制
     * @param {type}
     * @return:
     */
    draw(event) {
      this.ctx.lineTo(this.point.x, this.point.y)
      this.ctx.stroke()
    },
    /**
     * @description: 开始触摸
     * @param {type}
     * @return:
     */
    touchstart(event) {
      this.absolutePoint(event)
      this.ctx.moveTo(this.point.x, this.point.y)
    },
    /**
     * @description: 触摸结束
     * @param {type}
     * @return:
     */
    touchend(event) {},
    /**
     * @description: 触摸移动
     * @param {type}
     * @return:
     */
    touchmove(event) {
      this.absolutePoint(event)
      this.draw(event)
    }
  }
}

效果图

old.gif

问题

触摸坐标跟画图坐标不符,然后线条模糊

解决方案

在init方法里边重置canvas的高宽

    /**
     * @description: canvas 初始化
     * @param {type}
     * @return:
     */
    init() {
      const canvas = document.getElementById('canvas')
      const width = canvas.offsetWidth // ++
      const height = canvas.offsetHeight // ++
      this.ctx = canvas.getContext('2d')
      canvas.width = width // ++
      canvas.height = height // ++
      this.ctx.strokeStyle = '#474E60'
      this.ctx.lineWidth = 1
    },

问题原因

canvas 的宽高属性是必须通过属性设置的,因为需求原因,我的canvas通过父元素进行100%设置,通过重置canvas高宽可以解决问题。

完整实例

new.gif

完整代码

<template>
  <canvas id="canvas" @touchstart="touchstart" @touchend="touchend" @touchmove="touchmove"></canvas>
</template>

<script>
export default {
  data() {
    return {
      ctx: '',
      point: {
        x: 0,
        y: 0
      }
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    /**
     * @description: canvas 初始化
     * @param {type}
     * @return:
     */
    init() {
      const canvas = document.getElementById('canvas')
      const width = canvas.offsetWidth
      const height = canvas.offsetHeight
      this.ctx = canvas.getContext('2d')
      canvas.width = width
      canvas.height = height
      this.ctx.strokeStyle = '#474E60'
      this.ctx.lineWidth = 1
    },
    /**
     * @description: 获取相对坐标
     * @param {type}
     * @return:
     */
    absolutePoint(event) {
      const touch = event.targetTouches[0]
      const canvas = document.getElementById('canvas')
      const react = canvas.getBoundingClientRect()
      this.point = { x: touch.pageX - react.left, y: touch.pageY - react.top }
    },
    /**
     * @description: 绘制
     * @param {type}
     * @return:
     */
    draw(event) {
      this.ctx.lineTo(this.point.x, this.point.y)
      this.ctx.stroke()
    },
    /**
     * @description: 开始触摸
     * @param {type}
     * @return:
     */
    touchstart(event) {
      this.absolutePoint(event)
      this.ctx.moveTo(this.point.x, this.point.y)
    },
    /**
     * @description: 触摸结束
     * @param {type}
     * @return:
     */
    touchend(event) {},
    /**
     * @description: 触摸移动
     * @param {type}
     * @return:
     */
    touchmove(event) {
      this.absolutePoint(event)
      this.draw(event)
    }
  }
}
</script>

ps: 实例是以组件形式存在

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容