在上一篇canvas绘图的基础上做了延伸,做了一个绘图小程序。
下面附上draw文件夹下各文件的源码:
html文件 ----- draw.html:
<view class="container">
<canvas canvas-id="canvas" disable-scroll='true'
bindtouchstart="beginStroke"
bindtouchmove="moveStroke"
bindtouchend="endStroke"
style="width:{{canvasWidth}}rpx;height:{{canvasHeight}}rpx"
></canvas>
</view>
<view class="controller">
<view class="colorContr">
<block wx:for="{{colors}}">
<button bindtap="selectColor" class="colorBtn {{curColor == item ? 'selected' : ''}}" data-value="{{item}}" style="background-color:{{item}}"></button>
</block>
</view>
<slider bindchange='changeBold' min="1" max="20" value="5" block-size="18"/>
<button bindtap="clearCanvas" class="clearBtn"><image src="../imgs/reset.png" mode="aspectFit"></image></button>
<button bindtap="eraser" class="clearBtn {{isEraser ? 'selected' : ''}}"><image src="../imgs/eraser-v3.png" mode="aspectFit"></image></button>
</view>
<button class="saveImg" bindtap='saveImg'>保存</button>
<text class="sucTip" hidden="{{isSuc}}">保存成功</text>
css文件 ----- draw.css:
/* pages/draw/draw.wxss */
.container{
width:604rpx;
height:604rpx;
overflow: hidden;
margin:40rpx auto;
border: 1px solid #91d487;
padding:1rpx;
}
.controller{
width:600rpx;
margin:30rpx auto;
}
.controller slider{
width:360rpx;
float:left;
margin:10rpx 0;
}
.controller .colorContr{
overflow: hidden;
margin-bottom:40rpx;
}
.controller .colorBtn{
width:29px;
height:29px;
margin:3px;
float:left;
padding:0;
border:3px solid #fff;
}
.controller .selected{
border:1px solid #666;
}
.clearBtn{
width:80rpx;
height:60rpx;
float:right;
padding:0;
margin:0 10rpx;
line-height:60rpx;
font-size:30rpx;
background:none;
}
.clearBtn::after{
border:none;
}
.clearBtn image{
width:100%;
height:100%;
}
.saveImg{
position:fixed;
bottom:8rpx;
left:50%;
margin-left:-80rpx;
width:132rpx;
height:132rpx;
line-height:132rpx;
font-size:34rpx;
font-weight: bold;
letter-spacing: 5rpx;
background:#91d487;
color:#ffffff;
border-radius: 50%;
border:0;
box-shadow: 3px 3px 3px #aaa;
text-align:center;
}
.saveImg.button-hover{
background:#82c078;
color:#efefef;
}
.sucTip{
/* display:block; */
position:fixed;
bottom:35%;
left:50%;
transform: translateX(-50%);
color:#fff;
padding:10rpx 20rpx;
border-radius: 5px;
background:#91d487;
}
js文件 ----- draw.js:
Page({
/**
* 页面的初始数据
*/
data: {
canvasWidth:'600',
canvasHeight: 0,
boldVal:5,
colors: ['black', 'pink', 'red', 'skyblue', 'greenyellow', '#00FF00', '#0000FF', '#FF00FF','#00FFFF',
'#FFFF00', '#70DB93', '#5C3317 ', '#9F5F9F', '#B5A642', '#FF7F00','#42426F'],
curColor:'#000000',
isEraser:false,
isSuc:true,
isTap:true,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.context = wx.createCanvasContext('canvas');
this.setData({ canvasHeight: this.data.canvasWidth})
this.isMouseDown=false
this.lastLoc={ x: 0, y: 0 }
this.lastTimestamp = 0;
this.lastLineWidth = -1;
this.drawBgColor();
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
// this.setData({context: });
},
drawBgColor(){
this.context.save();
this.context.setFillStyle('#ffffff');
this.context.fillRect(0, 0, this.data.canvasWidth, this.data.canvasHeight)
this.context.restore();
this.context.draw({
reserve: true
})
},
changeBold:function(e){
this.setData({boldVal: e.detail.value})
},
selectColor:function(e){
this.setData({ curColor: e.currentTarget.dataset.value })
this.setData({ isEraser: false })
},
beginStroke(event) {
this.isMouseDown = true
this.lastLoc = { x: event.touches[0].x, y: event.touches[0].y }
this.lastTimestamp = event.timeStamp;
this.setData({ isTap: true })
// //draw
this.context.arc(this.lastLoc.x, this.lastLoc.y, this.data.boldVal / 2, 0, 2 * Math.PI)
this.context.setFillStyle(this.data.curColor);
this.context.fill();
wx.drawCanvas({
canvasId: 'canvas',
reserve: true,
actions: this.context.getActions() // 获取绘图动作数组
})
// if (event.touches.length>1){
// var xMove = event.touches[1].x - event.touches[0].x;
// var yMove = event.touches[1].y - event.touches[0].y;
// this.lastDistance = Math.sqrt(xMove * xMove + yMove * yMove);
// }
},
endStroke(event) {
// console.log(this.data.isTap)
// if (this.data.isTap){
// this.lastLoc = { x: event.changedTouches[0].x, y: event.changedTouches[0].y }
// this.lastTimestamp = event.timeStamp;
// //draw
// this.context.arc(this.lastLoc.x, this.lastLoc.y, this.data.boldVal / 2, 0, 2 * Math.PI)
// this.context.setFillStyle(this.data.curColor);
// this.context.fill();
// wx.drawCanvas({
// canvasId: 'canvas',
// reserve: true,
// actions: this.context.getActions() // 获取绘图动作数组
// })
// }
this.isMouseDown= false
},
moveStroke(event) {
if (this.isMouseDown && event.touches.length == 1) {
var touch = event.touches[0];
var context = this.context;
var curLoc = { x: touch.x, y: touch.y };
var curTimestamp = event.timeStamp;
var s = this.calcDistance(curLoc, this.lastLoc)
var t = curTimestamp - this.lastTimestamp;
var lineWidth = this.calcLineWidth(t, s)
//draw
context.setStrokeStyle(this.data.curColor);
context.setLineWidth(lineWidth);
context.beginPath()
context.moveTo(this.lastLoc.x, this.lastLoc.y)
context.lineTo(curLoc.x, curLoc.y)
// locHistory.push({ x: curLoc.x, y: curLoc.y, with: lineWidth, t: t })
context.setLineCap("round")
context.setLineJoin("round")
context.stroke();
this.lastLoc=curLoc;
// this.setData({ lastTimestamp: curTimestamp })
// this.setData({ lastLineWidth: lineWidth })
wx.drawCanvas({
canvasId: 'canvas',
reserve: true,
actions: this.context.getActions() // 获取绘图动作数组
})
} else if (event.touches.length > 1){
this.setData({isTap:false})
var xMove = event.touches[1].x - event.touches[0].x;
var yMove = event.touches[1].y - event.touches[0].y;
var newdistance = Math.sqrt(xMove*xMove + yMove*yMove);
// if (newdistance - this.lastDistance>0){
// this.setData({ canvasWidth: this.data.canvasWidth * 1.2 })
// this.setData({ canvasHeight: this.data.canvasHeight * 1.2 })
// }else{
// this.setData({ canvasWidth: this.data.canvasWidth * 0.8 })
// this.setData({ canvasHeight: this.data.canvasHeight * 0.8})
// }
}
},
calcLineWidth(t, s){
var v = s / t;
var resultLineWidth = this.data.boldVal;
if(v <= 0.1) {
resultLineWidth = resultLineWidth * 1.2;
}else if(v >= 10) {
resultLineWidth = resultLineWidth/1.2
}else{
resultLineWidth = resultLineWidth - (v - 0.1) / (10 - 0.1) * (resultLineWidth * 1.2 - resultLineWidth / 1.2)
}
return resultLineWidth
},
calcDistance(loc1, loc2) {
return Math.sqrt((loc1.x - loc2.x) * (loc1.x - loc2.x) + (loc1.y - loc2.y) * (loc1.y - loc2.y))
},
clearCanvas:function(){
this.drawBgColor()
this.setData({ isEraser:false})
},
eraser:function () {
this.setData({ isEraser: !this.data.isEraser})
this.setData({ curColor:'#ffffff'})
// this.context.clearActions();
// this.context.draw()
},
saveImg:function(){
var that = this;
var keys = wx.getStorageSync('myImg') || [];
console.log(that.data.keyLength)
wx.canvasToTempFilePath({
canvasId: 'canvas',
success: function (response) {
keys.unshift(response.tempFilePath)
wx.setStorage({
key: 'myImg',
data: keys,
})
that.setData({ isSuc: false })
setTimeout(function () {
that.setData({ isSuc: true })
wx.navigateTo({
url: '../index/index',
})
}, 1000)
}
})
}
})
小程序中canvas的具体用法和属性请参考小程序文档。