网上找了个插件,scratch.js下载地址:https://github.com/FrontendMing/scratch-in-wx-miniprogram
个人对scratch.js做了一些修改,设置清除面积达到一定值时(if (clearNum > .2) ),使刮卡刮干净,并触发(结果交互)方法;
测试时 调试基础库(project.config.json 文件中参数:"libVersion": "2.2.4",)设置成 2.2.4及以上,否则刮奖操作时没有反应,以下贴出代码
scratch.js代码:
class Scratch {
constructor(page, opts) {
opts = opts || {};
this.page = page;
this.canvasId = opts.canvasId || 'canvas';
this.width = opts.width || 300;
this.height = opts.height || 300;
this.maskColor = opts.maskColor || '#dddddd';
this.size = opts.size || 15,
//this.r = this.size * 2;
this.r = this.size;
this.area = this.r * this.r;
//this.scale = opts.scale || 0.7;
this.scale = opts.scale || .5;
this.totalArea = this.width * this.height;
this.init();
}
init() {
this.show = false;
this.clearPoints = [];
this.ctx = wx.createCanvasContext(this.canvasId, this);
this.drawMask();
this.bindTouch();
}
drawMask() {
this.ctx.setFillStyle(this.maskColor);
this.ctx.fillRect(0, 0, this.width, this.height);
this.ctx.draw();
}
bindTouch() {
this.page.touchStart = (e) => {
this.eraser(e, true);
}
this.page.touchMove = (e) => {
this.eraser(e, false);
}
this.page.touchEnd = (e) => {
if (this.show) {
this.page.clearCanvas();
this.ctx.clearRect(0, 0, this.width, this.height);
this.ctx.draw();
}
}
}
eraser(e, bool) {
let len = this.clearPoints.length;
let count = 0;
let x = e.touches[0].x,
y = e.touches[0].y;
let x1 = x - this.size;
let y1 = y - this.size;
if (bool) {
this.clearPoints.push({
x1: x1,
y1: y1,
x2: x1 + this.r,
y2: y1 + this.r
})
}
for (let item of this.clearPoints) {
if (item.x1 > x || item.y1 > y || item.x2 < x || item.y2 < y) {
count++;
} else {
break;
}
}
if (len === count) {
this.clearPoints.push({
x1: x1,
y1: y1,
x2: x1 + this.r,
y2: y1 + this.r
});
}
//添加计算已清除的面积,达到标准值后,设置刮卡区域刮干净
let clearNum = parseFloat(this.r * this.r * len) / parseFloat(this.scale * this.totalArea);
if (!this.show) {
this.page.setData({
clearNum: parseFloat(this.r * this.r * len) / parseFloat(this.scale * this.totalArea)
})
}
if (clearNum > .2) {
//if (len && this.r * this.r * len > this.scale * this.totalArea) {
this.show = true;
}
this.clearArcFun(x, y, this.r, this.ctx);
this.ctx.draw(true);
}
clearArcFun(x, y, r, ctx) {
let stepClear = 1;
clearArc(x, y, r);
function clearArc(x, y, radius) {
let calcWidth = radius - stepClear;
let calcHeight = Math.sqrt(radius * radius - calcWidth * calcWidth);
let posX = x - calcWidth;
let posY = y - calcHeight;
let widthX = 2 * calcWidth;
let heightY = 2 * calcHeight;
if (stepClear <= radius) {
ctx.clearRect(posX, posY, widthX, heightY);
stepClear += 1;
clearArc(x, y, radius);
}
}
}
}
export default Scratch
使用demo:
.js:
var app = getApp();
import Scratch from '../../utils/scratch.js'
let cjIn = false; //防止多次点击
Page({
/**
* 页面的初始数据
*/
data: {
gjEnd: false, //是否刮奖结束
showGjBth: true, //是否显示刮奖按钮
again: false, //是否显示再来一次按钮
cjNum: '', //抽奖机会
resaultSrc: '', //中奖显示图
hasPrize: '', //是否中奖
prizeName: '', //奖品名称
},
//刮奖设置
gj() {
let This = this;
if (!This.data.cjNum) {
wx.showModal({
title: '很抱歉',
content: '没有机会啦~',
showCancel: false,
success(res) {
}
})
return;
}
if (cjIn) {
return;
} else {
cjIn = true;
}
// let dataJson = {
//
// };
// wx.showLoading({
// title: '页面加载中',
// })
//获取抽奖结果
// app._post_form(
// '获取抽奖结果',
// dataJson,
// (res) => {
// res = res.data;
//
// console.log(res);
let timeOutTime = 0; //再次 刮奖时要先显示CANVAS,如果显示CANVAS 与 初始化刮奖界面同时进行的话,则不能重置刮奖层状态
if (This.data.gjEnd) {
//先显示CANVAS
This.setData({
gjEnd: false, //是否刮奖结束
});
timeOutTime = 100;
}
setTimeout(function() {
//初始化刮奖界面 ,重置刮奖层状态
new Scratch(This, {
canvasId: 'canvas-demo',
width:570,
height:213,
//maskColor:'#dddddd',
//size:15,
//scale:1,
scale:.5,
})
setTimeout(function() {
//重置刮奖层状态后,再绑定 获取到的结果 数据,否则会出现结果先出来导致“闪动”的状态
This.setData({
showGjBth: false, //是否显示刮奖按钮
again: false, //是否显示再来一次按钮
//cjNum: 0, //抽奖机会
cjNum: 1, //抽奖机会
resaultSrc: '', //中奖显示图
hasPrize: true, //是否中奖
prizeName: '奖品名称XXX', //奖品名称
});
}, 100)
}, timeOutTime)
// wx.hideLoading();
// },
// (res) => {
// //失败
// console.log(res)
//
// cjIn = false;
//
// wx.hideLoading();
// },
// )
},
//刮卡已刮干净
clearCanvas() {
let This = this;
setTimeout(function() {
//隐藏CANVAS
This.setData({
gjEnd: true, //是否刮奖结束
});
}, 100)
if (!This.data.again) {
cjIn = false;
console.log('刮卡已刮干净啦!');
//刮卡刮干净后 显示的界面 ,显示再刮一次按钮(页面中已注释)
This.setData({
again: true,
});
}
},
//获取抽奖机会次数
getNum() {
let This = this;
This.setData({
cjNum: 1,
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function() {
cjIn = false;
let This = this;
This.setData({
gjEnd: false, //是否刮奖结束
showGjBth: true, //是否显示刮奖按钮
again: false,//是否显示再来一次按钮
resaultSrc: '', //中奖显示图
hasPrize: '', //是否中奖
});
This.getNum(); //获取抽奖机会次数
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function() {
}
})
.wxss:
page{ box-sizing: border-box; padding-top: 50rpx; background-color: #3b0a8e;}
.scratch_body{ width: 630rpx; padding-top: 24rpx; margin: 0 auto; position: relative;}
.scratch_body_bg{ width: 100%; position: absolute; left: 0; top: 0;}
.scratch_time{ width: 440rpx; height: 64rpx; margin: 0 auto 20rpx auto; text-align: center; color: #e81903; font-size: 28rpx; position: relative;}
.scratch_time text{ font-size: 42rpx;}
.scratch_do{ width: 570rpx; height: 213rpx;/* margin: 0 auto 160rpx auto; */ margin: 0 auto 110rpx auto; position: relative;}
.scratch_do_after , .scratch_do_after_box , .scratch_do_after_box image , .scratch_do_in , .scratch_do_before{ width: 100%; height: 100%; position: absolute; left: 0; top: 0;}
.scratch_do_after_box{ padding-top: 25rpx; line-height: 82rpx; color: #7a7a7a; font-size: 40rpx; text-align: center;}
.scratch_do_after_box view{ position: relative;}
.scratch_do_after_btn{ width: 210rpx; height: 54rpx; line-height: 54rpx; margin: 0 auto; color: #fff; font-size: 30rpx; border-radius: 27rpx; background-color: #ff3c9d;}
.scratch_btn{ width: 310rpx; height: 64rpx; margin: 34rpx auto 0 auto; border: #fff solid 2rpx; border-radius: 32rpx; position: relative;
display: flex; justify-content: center; align-items: center;
box-shadow: 0 0 15px 5px rgba(102,12,164,.8);
}
.scratch_btn view{ width: 300rpx; height: 52rpx; line-height: 52rpx; text-align: center; color: #3b0a8e; font-size: 30rpx; font-weight: bold; background-color: #fff; border-radius: 26rpx;}
.wxml:
<view class="scratch_body">
<image class="scratch_body_bg" mode="widthFix" src="https://img-blog.csdnimg.cn/2022010702543295939.png"></image>
<view class="scratch_time">您有 <text>{{cjNum}}</text> 次刮奖机会</view>
<view class="scratch_do">
<view class="scratch_do_after">
<view wx:if="{{hasPrize}}" class="scratch_do_after_box">
<image mode="widthFix" src="https://img-blog.csdnimg.cn/2022010702543242350.png"></image>
<view>恭喜你刮中{{prizeName}}</view>
<view class="scratch_do_after_btn" bindtap="gj">再来一次</view>
</view>
<view wx:else class="scratch_do_after_box">
<view>很遗憾未中奖</view>
<view class="scratch_do_after_btn" bindtap="gj">再来一次</view>
</view>
</view>
<canvas wx:if="{{!gjEnd}}" class="scratch_do_in" disable-scroll="false" canvas-id='canvas-demo' bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd"></canvas>
<cover-image wx:if="{{showGjBth}}" class="scratch_do_before" src="https://img-blog.csdnimg.cn/2022010702543256236.png" bindtap="gj"></cover-image>
<!-- <view wx:if="{{again}}" class="scratch_btn again_btn" bindtap="gj">
<view>再刮一次</view>
</view> -->
</view>
<view class="scratch_btn">
<view>我的奖品</view>
</view>
<view class="scratch_btn">
<view>活动规则</view>
</view>
</view>