效果:
简单说明:
由于 canvas2D 的实例需要获取到 canvas 的容器元素,因此我们最早只能在页面 onReady 中调用初始化函数,如果在 onLoad 或者 onShow 中调用该函数,则无法获取到 canvas 容器元素
触摸开始的时候和旧版的canvas 接口是一样的,需要 moveTo 到起始点
在 canvas2D 绘制的时候和旧版的 canvas 不同:canvas2D 只需要 lineTo() > stroke() > moveTo() 即可,不需要显式的调用 draw() 方法,要比旧版的 canvas 更为细腻
完整代码如下: wxml
<canvas id="myCanvas" type="2d" class="canvas" style="width:{{width+'px'}};height:{{height+'px'}}" catchtouchstart="catchtouchstart" catchtouchmove="catchtouchmove" catchtouchend="catchtouchend"></canvas>
<view class="btn-reset" catchtap="clearCanvas">重新签名</view>
<view class="btn-ok" catchtap="canvasToImg">确认</view>
wxss
page{
position: relative;
background-color: #f2f2f2;
width: 100%;
height: 100%;
}
canvas{
width: 100%;
height: 100vh;
}
.myCanvas{
background-color: red;
}
.btn-reset{
width: 130rpx;
position: absolute;
bottom: 30rpx;
right: 180rpx;
padding: 8rpx;
text-align: center;
border: 1rpx solid #4965B3;
color: #4965B3;
font-size: 12px;
border-radius: 24rpx;
box-sizing: border-box;
}
.btn-ok{
width: 130rpx;
position: absolute;
bottom: 30rpx;
right: 30rpx;
padding: 8rpx;
text-align: center;
background-color: #4965B3;
border: 1rpx solid #4965B3;
color: #fff;
font-size: 12px;
border-radius: 24rpx;
box-sizing: border-box;
}
js
Component({
data: {
canvas:null,
ctx: null,
width: 385,
height: 650,
drawCount: 0,
drawState: "init",
points:[]
},
methods:{
initCanvas() {
wx.nextTick(()=>{
const query = wx.createSelectorQuery().in(this)
query.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res) => {
// Canvas 对象
const canvas = res[0].node
// Canvas 画布的实际绘制宽高
const renderWidth = res[0].width
const renderHeight = res[0].height
// Canvas 绘制上下文
const ctx = canvas.getContext('2d')
this.data.ctx = ctx
this.data.canvas = canvas
// 初始化画布大小
const dpr = wx.getWindowInfo().pixelRatio
canvas.width = renderWidth * dpr
canvas.height = renderHeight * dpr
ctx.scale(dpr, dpr)
this.clearCanvas()
})
})
},
clearCanvas() {
const { ctx,canvas } = this.data
this.data.drawCount = 0
this.data.drawState = "ing"
ctx.textBaseline = 'top'
ctx.textAlign = 'center'
ctx.fontSize = '20'
ctx.font = '24px red'
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = '#616165'
ctx.fillText("请在区域内完成签名", this.data.width / 2, this.data.height/2 - 40)
},
catchtouchstart(e) {
const { canvas } = this.data
if (this.data.drawCount == 0) {
this.data.ctx.beginPath()
this.data.ctx.clearRect(0,0,canvas.width,canvas.height)
}
this.data.drawCount++
this.data.ctx.moveTo(e.changedTouches[0].clientX, e.changedTouches[0].clientY)
},
catchtouchmove(e) {
const { ctx } = this.data
if (this.data.drawState == "stop") return
this.data.drawState = "ing"
if (e.touches.length > 1) {
return
}
ctx.strokeStyle = '#000000';
ctx.LineWidth = 4;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowColor = '#000000';
ctx.shadowBlur = 1;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.lineTo(e.changedTouches[0].clientX, e.changedTouches[0].clientY)
ctx.stroke()
ctx.moveTo(e.changedTouches[0].clientX, e.changedTouches[0].clientY)
},
catchtouchend(e) {
this.data.points = []
},
canvasToImg() {
const { canvas } = this.data
if (this.data.drawState == "init") return
this.data.drawState = "stop"
wx.canvasToTempFilePath({
canvas: canvas,
success: (res) => {
console.log(res.tempFilePath)
},
fail(rej){
console.log(rej)
}
})
}
},
pageLifetimes:{
show: function () {
this.initCanvas()
},
}
})