笔者今年刚毕业,也没从业经历,难免有代码编写不成熟的地方,欢迎指正
上周开始接触小程序,这里实现的功能类似表情包制作:选择图片、输入文字后保存到本地。目前只是demo 后续会不断完善所以不是最终效果
下面是界面效果
该页面的data:
//字号
for(let i=12; i<32; i++)
{
fontsize.push(i)
}
data: {
fontsize:fontsize,
sizeindex:0,
textsize:0,
textlength:0,
imgurl:"",
textvalue:"",
x:0,
y:0,
fontcolorrange: ['黑', '粉红', '纯红', '紫罗兰', '蓝色', '绿宝石', '金', '深橙色','白色'],
fontcolorhex: ['#000000', '#FF69B4', '#ff0000', '#9400D3', '#0000FF', '#00FA9A', '#FFD700', '#FF8C00', '#ffffff'],
colorIndex:0,
tempfile:"",
canvasWidth:675,
canvasHeight:0,
imgwidth:0,
imgheight:0,
textIsClick:false,
EmoPic: ['/img/Emoticon1.jpg', '/img/Emoticon2.jpg', '/img/Emoticon3.jpg','/img/Emoticon4.jpg'],
EmoIndex:0,
EmoButtonIsClick:false,
EmoHeight:1,
ishavePic:false
}
我的思路是使用两个canvas分别用于绘制图片和文字,文字样式使用picker选择数据。
上方选择图片区域使用【cover-view】,做absolute定位。由于canvas作为原生组件会显示在最上层所以不能用【view】,遗憾的是cover-view不能实现css的transition动画及其他效果。【选择图片】按钮嵌套在cover-view内,点击时控制cover-view显示和隐藏(控制height)
选择图片触发bindtap事件,函数bindEmoPicChoose:
bindEmoPicChoose:function(e){
var that = this
var index = e.currentTarget.dataset.index
var EmoPic = that.data.EmoPic
that.setData({
imgurl: EmoPic[index],
ishavePic:true
})
that.canvasfunction()
}
canvasfunction函数用于在canvas根据‘imgurl’绘制图片
canvasfunction:function(){
var that = this
var mycanvas = wx.createCanvasContext("canvas-pic")
var imgwidth = that.data.imgwidth
var imgheight = that.data.imgheight
var imgurl = that.data.imgurl
var ishavePic = that.data.ishavePic
if (ishavePic == true)
{
mycanvas.drawImage(imgurl, 0, 0, imgwidth, imgheight)
}
else
{
mycanvas.setFillStyle("#000000")
mycanvas.setFontSize("20")
mycanvas.fillText("请选择一张图片吧~",app.globalData.screenWidth/2 - 100,(app.globalData.screenHeight)*0.3)
}
mycanvas.draw()
console.log("发生了canvasfunction")
console.log("ishavePic :" + ishavePic)
},
(图片另外有函数做宽高自适应处理)
触发canvasfunction函数后,在需要绘制图片的canvas就根据imgurl绘制图片,该函数在onshow时也会执行,由于没有图片则示意用户选择图片。imgwidth与imgheight是另外函数获取图片的宽高,然后做自适应的数值。
点击图片后canvas绘制了图片,接下来选择文字样式
文字内容、大小、颜色分别触发picker的bindchange事件相应函数,data中对应数据以数组的形式保存。bindchange的函数参照小程序官方开发文档。
【点我新增文字】按钮触发bindtap事件,事件函数如下:
canvasaddtext:function(){
var that = this
var mytext = wx.createCanvasContext("canvas-text")
var text = that .data.textvalue
var color = that .data.fontcolorhex[that .data.colorIndex]
mytext.setFillStyle(color)
mytext.setFontSize(that.data.fontsize[that.data.sizeindex])
mytext.fillText(text, 150, 150)
mytext.draw()
console.log("发生了canvasaddtext")
that.setData({
textsize: that.data.fontsize[that.data.sizeindex]
})
console.log("textsize:" + that.data.textsize)
}
该函数使canvas-id为canvas-text的canvas绘制文字
文字允许拖拽以改变位置,我们需要对文字所在canvas的bindtouchstart事件、bindtouchmove事件设置对应函数
bindtouchstart事件:保存用户当前点击位置x、y坐标的值
canvasmovestart:function(e){
var x = e.touches[0].x
var y = e.touches[0].y
this.setData({
x:x,
y:y,
})
console.log("x:" + e.touches[0].x)
console.log("y:" + e.touches[0].y)
}
bindtouchmove事件: 在手指移动后修改x、y坐标的值,并根据x、y值绘制canvas
canvasmoveon:function(e){
console.log("moveon!")
var x = e.touches[0].x
var y = e.touches[0].y
var textsize = this.data.textsize
var textlength = this.data.textlength
if(x<0){x = 0}
if (x + (textlength * textsize) > 280) { x = 280 - (textlength * textsize)}
if (y - (textsize) < 0){y = textsize}
if(y + (textsize)>300){ y = 300 - textsize}
console.log("x:" + x + " y:" + y)
var mytext = wx.createCanvasContext("canvas-text")
var text = this.data.textvalue
var color = this.data.fontcolorhex[this.data.colorIndex]
mytext.setFillStyle(color)
mytext.setFontSize(this.data.fontsize[this.data.sizeindex])
mytext.fillText(text, x, y)
mytext.draw()
this.setData({
x: x,
y: y,
textvalue: text
})
}
这里textsize保存的是文本的px值,textlength 是文本框文字长度(e.detail.value.length可获得),文本px值与文本长度的积是文字总像素长度,用于判断距离canvas右边距的位置。由于这里需要限制文本可拖拽范围不能超过canvas图片区,当大于这个范围时,对应的x、y值将被固定。
拖动文字的效果,实际上就是每当坐标值更改时,对canvas重新绘制。
拖动文字时不允许屏幕滚动,因此在canvas标签内添加【disable-scroll=‘true’】
清空画布按钮在右上角。由于在canvas上方,所以也需要嵌套在cover-view内,absolute定位,点击时触发bingtap事件,事件函数如下:
bindcanvasclear:function(){
this.setData({
ishavePic:false
})
this.canvasfunction()
this.canvascleartext()
},
canvascleartext:function(){
var mytext = wx.createCanvasContext("canvas-text")
mytext.fillText("",0,0)
mytext.draw()
console.log("发生了canvascleartext")
}
清除文本目前使用绘制空字符串的方法达到清除的效果
图片保存需要调用wx.canvasToTempFilePath 和 wx.saveImageToPhotosAlbum接口,分别用于获取导出图片的url及图片保存到本地
wx.showToast({
title: '图片生成中',
duration:1000
})
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: imgwidth,
height: imgheight,
canvasId: 'canvas-pic',
success: function (res) {
//var tempfile = res.tempFilePath
console.log(res.tempFilePath)
wx.hideToast()
temp = res.tempFilePath
wx.saveImageToPhotosAlbum({
filePath: temp,
success: function (data) {
console.log('图片保存成功!data:' + data)
},
fail: function (err) {
console.log("图片保存失败:error:" + err)
}
})
}
})
图片保存需要用户授权,在app.js中添加以下代码:
if (!res.authSetting['scope.writePhotosAlbum'])
{
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
console.log('图片保存授权成功')
}
})
}