在uni-app开发中,canvas.drawCanvas调用后没有反应是常见问题,很多开发者因此困惑。根本原因在于上下文未正确绑定到渲染目标。通过uni.createCanvasContext创建的上下文,在非H5平台默认绑定原生canvas组件,而在H5端则使用DOM canvas,两套底层机制
uni-app canvas刮刮乐抽奖技巧
时间:2026-07-29
浏览:549
文章目录
在uni-app开发中,canvas.drawCanvas调用后没有反应是常见问题,很多开发者因此困惑。根本原因在于上下文未正确绑定到渲染目标。通过uni.createCanvasContext创建的上下文,在非H5平台默认绑定原生canvas组件,而在H5端则使用DOM canvas,两套底层机制导致行为差异。真机调试时最容易出现“画了但看不见”的情况,核心就是context没有挂载到正确的canvas元素上。

uni-app canvas.drawCanvas 没反应的原因与解决方法
必须显式声明canvas组件,且canvas-id要与uni.createCanvasContext的第二个参数严格一致。很多开发者忽略这个细节,导致context使用错误的id查找组件,自然无法生效。
- 使用
明确声明,且canvas-id必须精确匹配 - H5端需额外添加
disable-scroll="true",否则用户触摸时页面滚动会干扰绘制坐标 - App和小程序端,需确保canvas组件已挂载渲染完成——在
onReady之后再初始化context,否则drawCanvas调用只会成为空指令
刮刮乐核心:利用 globalCompositeOperation 实现“刮开”效果
实现刮刮乐的关键不是“擦除”,而是利用canvas的混合模式让底层内容透出。先绘制遮罩层(例如灰色矩形)在最上层,然后将绘图模式切换为destination-out,用户在触摸路径上画的所有内容都会“挖掉”遮罩层,被划过的地方底层图片即可露出。
- 先用
fillStyle将整个canvas填满作为遮罩,例如ctx.fillStyle = '#ccc',然后填充整张画布 - 接着调用
ctx.globalCompositeOperation = 'destination-out',之后所有绘图都会“吃掉”现有像素 - 触摸移动时使用
lineTo加stroke连接路径,笔触宽度建议设置在20~40像素之间:太细刮不动,太粗响应会滞后 - H5端某些安卓WebView对
destination-out支持不稳定,此时可退而使用clearRect配合坐标映射模拟擦除,但需自行维护刮开区域的路径数据
touchmove 坐标如何对齐 canvas 实际尺寸?
用户手指触摸坐标是屏幕坐标系下的,而canvas通常会被缩放、居中或设置样式宽高。直接使用e.touches[0].clientX绘制,坐标必然偏移。必须进行设备像素比和canvas缩放因子的校准。
- 先通过
uni.getSystemInfoSync().pixelRatio获取设备像素比 - 再用
uni.createSelectorQuery()查询canvas元素的实际渲染尺寸(通过boundingClientRect),然后用实际宽高除以样式宽高得到缩放系数 - 最终坐标计算:x/y =
(touchX - left) * pixelRatio / scaleX,其中left是canvas左侧距视口的距离 - 注意:在
touchstart事件中必须调用ctx.beginPath(),否则lineTo会从画布原点开始连线,产生大量对角的线条
刮开面积达到阈值后如何触发中奖逻辑?
靠“画了多少像素”判断刮开比例,性能和精度都难以保证,且易受设备与坐标校准偏差影响。更稳妥的做法是维护一个离屏canvas或布尔型二维数组记录刮开区域,再统计透明像素占比,但该方案对小程序和H5来说较重。
一个轻量级替代方案是使用ctx.getImageData进行抽样检测。每刮100毫秒或每移动20像素,取canvas中心一个5×5区域的像素数据(ctx.getImageData(x, y, 5, 5)),遍历data数组检查alpha通道值是否小于10(表示已刮透),累计达标点数。当超过阈值(例如15/25)时,即可认为刮开——立即触发中奖回调,并停止抽样。
注意:H5端调用getImageData会触发跨域限制,canvas内容必须为同源图片或base64编码,否则获取的数据全为零。
刮开效果的稳定性和手感,80%取决于坐标校准与composite模式切换的时机,剩下20%是抽样检测的阈值与频率平衡——调得太松易误判,太严则用户刮到手酸也无法触发。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。