1.关键canvasAPI
globalCompositeOperation = “destination-out”; //橡皮擦模式,
2. HTML部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实现刮刮乐</title>
<style>
.img {
width: 400px;
height: 300px;
position: absolute;
left: 200px;
z-index: -1;
}
canvas {
margin-left: 200px;
}
body {
margin: 0;
}
</style>
</head>
<body>
<div class="img">
<img src="./images/1.png" style="width:100%;height:100%;" />
</div>
<canvas id="canvas" width="400" height="300"></canvas>
</body>
实现的效果:图片被灰色的涂层遮盖住,类似刮刮乐的表面。如下图所示
3.给canvas设置监听函数
(1) 因为我们要实现刮刮乐的效果,需要对鼠标事件进行监听,然后把新的图层绘制在canvas上面,让图片露出表面。
let canvas = document.querySelector("#canvas");
let context = canvas.getContext("2d");
//绘制涂层(灰色部分)
context.beginPath();
context.fillStyle = "grey";
context.fillRect(0, 0, 400, 300);//设置画布大小
//监听鼠标事件
canvas.addEventListener("mousemove", (e) => {
//当鼠标左键按下&&移动鼠标时,清除鼠标附近涂层
if (e.which === 1 && e.button === 0) {
const x = e.clientX, y = e.clientY;
context.globalCompositeOperation = "destination-out"; //橡皮擦模式
context.beginPath();
//以鼠标位置为圆心,半径为10px的园
context.arc(x - 200, y, 10, 0, Math.PI * 2); //x-200 ,200是宽度的一半
context.fill();
}
})
4. 实现效果
5进阶版刮刮乐
(1)一般的,我们不需要全部刮完灰色的部分,刮到一定程度了,便可以全部显示出来。为了达到这个效果,需要增加两个功能,一个是判断刮的面积,另一个是全部显示。判断面积使用 calcClearArea 函数,clear 函数为逐渐消失的效果。
//计算已经擦除的面积与原画布面积占比
function calcClearArea() {
//获取canvas 的像素信息
const pixels = context.getImageData(0, 0, 400, 300).data;
let transparentPixels = 0;
for (let i = 0; i < pixels.length; i += 4) {
if (pixels[i + 1] < 128) {
transparentPixels++
}
}
console.log((transparentPixels / pixels.length * 4 * 100).toFixed(2))
return (transparentPixels / pixels.length * 4 * 100).toFixed(2)
}
//清除涂层
function clear(alpha) {
return () => {
context.save();
context.globalCompositeOperation = "source-in";
context.fillStyle = context.fillStyle + (alpha -= 1).toString(16);
context.fillRect(0, 0, 400, 300);
context.restore();
if (alpha > 210) {
requestAnimationFrame(clear(alpha))
}
}
然后,给鼠标抬起事件加上监听,当刮刮的面积达到整体的30%,则自动清除剩下的面积。
canvas.addEventListener("mouseup", (e) => {
const pixels = calcClearArea();
if (pixels >= 30) {
requestAnimationFrame(clear(255));
}
})