一.刮刮乐功能
1.做法
主要是要使用canvas画布去绘制刮奖图层,再监听划动,清除掉绘制的区域,达到某个占比之后直接清空刮奖图层。
首先wxml里面就是常规的设置canvas,需要设置好宽高。注意canvas会盖住其他图层。
<canvas canvas-id='scratchCanvas' id='scratchCanvas' style="width:{{width}}px;height:{{height}}px;" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd"></canvas>
先在onReady的时候设置一下 wx.createCanvasContext('scratchCanvas'),然后在touchStart跟touchMove的时候设置清空函数eraser。earser中记录划动的时候的点,let x = e.touches[0].x, y = e.touches[0].y,并加上触碰的范围大小,保存到clearPoints数组。
定义了一个scale来控制实现的达到某个比例之后清空图层
if (this.data.clearPoints.length && this.data.r * this.data.r * this.data.clearPoints.length > this.data.scale * this.data.totalArea) {
this.data.showAward = true;//刮完奖品,是可领奖状态
}
this.data.scratchCanvas.clearRect(x1, y1, this.data.r, this.data.r);
this.data.scratchCanvas.draw(true);
2.遇到的问题
2.1 canvas绘制圆角
canvas需要绘制刮奖图层,最开始使用常规fillRect就可以绘制,
this.data.scratchCanvas.setFillStyle(this.data.maskColor);
this.data.scratchCanvas.fillRect(0, 0, this.data.width, this.data.height);
this.data.scratchCanvas.draw();
但是后来展示需要圆角,那就不能直接使用了,使用arc可以绘制4个边角的圆角,如:
ctx.arc(320/2, 320/2, 320/2, 0, 2 * Math.PI);
2.2 刮奖层使用图片
原先是一个纯色的一个刮奖图层,要使用图片的话,只需要奖fillRect相关的,替换成图片的处理drawImage,再结合圆角需求的处理,如:
const ctx = wx.createCanvasContext(this.data.canvasId)
// 图片的x坐标
let bg_x = 0
// 图片的y坐标
let bg_y = 0
// 图片宽度
let bg_w = this.data.width
// 图片高度
let bg_h = this.data.height
// 图片圆角
let bg_r = 10
ctx.beginPath()
//ctx.arc(320/2, 320/2, 320/2, 0, 2 * Math.PI);
ctx.arc(bg_x + bg_r, bg_y + bg_r, bg_r, Math.PI, Math.PI*1.5)
ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_r, bg_r, Math.PI * 1.5, Math.PI * 2)
ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_h - bg_r, bg_r, 0, Math.PI * 0.5)
ctx.arc(bg_x + bg_r, bg_y + bg_h - bg_r, bg_r, Math.PI * 0.5, Math.PI)
ctx.clip();
ctx.drawImage('../../images/mask1.png', bg_x, bg_y, this.data.width, this.data.height)
// ctx.setFillStyle(this.data.maskColor);
// ctx.fillRect(0, 0, this.data.width, this.data.height);
ctx.draw()
本来还想使用filter,开发者工具能生效,但是真机无效,所以没动。
2.3 canvas层级问题
问题:弹窗点开之后在canvas下层。开发者工具不会,但是真机被盖住了。
解决:这里做的处理是先打开的时候设置了一下canvas的witdh为0,需要注意绘制的时候,要修改为设定的宽度。
3.其他常规逻辑
3.1返回的时候弹出领奖提示
需求是刮中大奖之后需要提交对应的信息的,所以希望退出的时候有二次确认
3.1.1小程序页面返回询问对话框。
使用微信自带API
wx.enableAlertBeforeUnload({
message:'跳出当前页面,刮奖记录将不会保存',
})
出现条件:
- 当用户在小程序内非首页页面/最底层页
- 官方导航栏上的的返回
- 全屏模式下自绘返回键
- android 系统 back 键时
3.1.2 领奖信息弹窗关闭时候提示
使用官方的showModal
wx.showModal({
content: '您还没领取奖励,确认再刮?',
confirmText: "确认",
cancelText: "取消",
success: (res) => {
console.log(res);
//点击“确认”时打开设置页面
if (res.confirm) {
console.log('用户点击确认')
this.init();
} else {
console.log('用户点击取消')
}
}
});
3.2 云函数与普通URL的下载处理
功能需要保存图片,在最初未确定如何存储的时候,做了两手准备。
3.2.1 云函数处理
先检测是否有授权打开相册权限,确认后可以打开设置。
wx.openSetting({
success: (res) => {
}
})
如果打开了直接使用云函数下载,这里的地址需要在wxml文件中设置data-url='xxx'(资源文件的fileID),再使用wx.saveImageToPhotosAlbum下载
wx.cloud.downloadFile({
fileID: e.currentTarget.dataset.url,
success: res => {
// get temp file path
console.log(res.tempFilePath)
wx.saveImageToPhotosAlbum({//保存到本地
filePath: res.tempFilePath,
success(res) {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
fail: function (err) {
if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
fail && fail();
}
}
})
},
fail: err => {
// handle error
}
})
3.2.2 常规的地址下载
使用的是wx.downloadFile。
wx.downloadFile({
url: e.currentTarget.dataset.url, //需要下载的图片url
success: function (res) { //成功后的回调函数
wx.saveImageToPhotosAlbum({ //保存到本地
filePath: res.tempFilePath,
success(res) {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
fail: function (err) {
if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
fail && fail();
}
}
})
},
fail:function(res){
// fail && fail();
console.log('resss=',res)
wx.showToast({
title: '保存失败',
icon: 'none',
duration: 2000
})
}
});
3.3 预览图片
如果刮开的是梗图,那还点击打开还需要大图展示,所以还需要图片预览功能,使用wx.previewImage
wx.previewImage({
urls: [url],
current: 0,
});
3.4 ‘再刮一次’分享按钮处理
3.4.1 分享按钮
因为目前是包含免费次数以及分享增加次数,所以其中需要有分享按钮。微信小程序需要设置对应的button的open-type属性才可以分享。这里使用了一个button一个view节点来处理2种情况。
<button class="bottomBtn" open-type="share" plain="{{true}}" wx:if="{{!canScratch}}" >
<image src="../../assets/btn_common_blue.png" mode="scaleToFill" class="btn_img1"/>
<text>再刮一次</text>
</button>
<view class="bottomBtn" bindtap="again" wx:if="{{canScratch}}">
<image src="../../assets/btn_common_blue.png" mode="scaleToFill" class="btn_img1"/>
<text>再刮一次</text>
</view>
只有有次数的时候才显示view的内容,否则显示open-type为share的button按钮,点击之后拉起分享。
3.4.2 分享按钮记录次数
分享的时候需要记录按钮点击次数以及分享的次数,需要在onShareAppMessage中调用云函数并刷新页面