需求
通過(guò)canvas來(lái)實(shí)現(xiàn)觸摸板來(lái)寫(xiě)下一些題目的解題步驟,然后使用設(shè)備是手機(jī)跟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: 獲取相對(duì)坐標(biāo)
* @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: 開(kāi)始觸摸
* @param {type}
* @return:
*/
touchstart(event) {
this.absolutePoint(event)
this.ctx.moveTo(this.point.x, this.point.y)
},
/**
* @description: 觸摸結(jié)束
* @param {type}
* @return:
*/
touchend(event) {},
/**
* @description: 觸摸移動(dòng)
* @param {type}
* @return:
*/
touchmove(event) {
this.absolutePoint(event)
this.draw(event)
}
}
}
效果圖
old.gif
問(wèn)題
觸摸坐標(biāo)跟畫(huà)圖坐標(biāo)不符礼殊,然后線條模糊
解決方案
在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
},
問(wèn)題原因
canvas 的寬高屬性是必須通過(guò)屬性設(shè)置的果正,因?yàn)樾枨笤颍业腸anvas通過(guò)父元素進(jìn)行100%設(shè)置,通過(guò)重置canvas高寬可以解決問(wèn)題帜消。
完整實(shí)例
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: 獲取相對(duì)坐標(biāo)
* @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: 開(kāi)始觸摸
* @param {type}
* @return:
*/
touchstart(event) {
this.absolutePoint(event)
this.ctx.moveTo(this.point.x, this.point.y)
},
/**
* @description: 觸摸結(jié)束
* @param {type}
* @return:
*/
touchend(event) {},
/**
* @description: 觸摸移動(dòng)
* @param {type}
* @return:
*/
touchmove(event) {
this.absolutePoint(event)
this.draw(event)
}
}
}
</script>
ps: 實(shí)例是以組件形式存在