<!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>Canvas创意</title>
<script src="../libs/Ticket.js"></script>
<style>
body {
margin: 0px;
}
</style>
</head>
<body>
<div>
<canvas id="canvas-ticket"></canvas>
</div>
<script type="text/javascript">
(function () {
let canvasTicket = document.getElementById("canvas-ticket");
let ticket = new Ticket();
ticket.init(
canvasTicket,
"https://file.idongjia.cn/T3MpCgB7CT1RCvBVdK.png",
"https://file.idongjia.cn/T3tKAgBXYT1RCvBVdK.png",
() => {
ticket.clean();
}
);
})();
</script>
</body>
</html>
class Ticket {
constructor() {
this.ctx = null;
this.imgData = null;
this.isDown = false;
this.img = new Image();
this.pst = 0.5;
this.backFun = null;
}
init(canvas, bg, cover, backFun = null, pst = 0.5) {
this.backFun = backFun;
this.pst = pst;
this.ctx = canvas.getContext("2d");
canvas.style.backgroundImage = "url(" + bg + ")";
canvas.style.backgroundPosition = "center";
canvas.style.backgroundRepeat = "no-repeat";
canvas.style.backgroundSize = "contain";
this.img.crossOrigin = "";
this.img.src = cover;
this.img.onload = () => {
canvas.width = this.img.width;
canvas.height = this.img.height;
this.ctx.drawImage(this.img, 0, 0, this.img.width, this.img.height);
};
canvas.addEventListener("mousemove", (event) => {
this.move(event.offsetX, event.offsetY);
});
canvas.addEventListener("mousedown", () => {
this.start();
});
canvas.addEventListener("mouseup", () => {
this.end();
});
canvas.addEventListener("touchmove", (e) => {
let dx = canvas.offsetLeft;
let dy = canvas.offsetTop;
let offsetX = e.touches[0].pageX - dx;
let offsetY = e.touches[0].pageY - dy;
this.move(offsetX, offsetY);
});
canvas.addEventListener("touchstart", () => {
this.start();
});
canvas.addEventListener("touchend", () => {
this.end();
});
}
start() {
this.isDown = true;
}
move(offsetX, offsetY) {
if (this.isDown) {
let x = offsetX;
let y = offsetY;
this.ctx.beginPath();
this.ctx.fillStyle = "white";
this.ctx.arc(x, y, 20, Math.PI * 2, false);
this.ctx.fill();
this.ctx.closePath();
this.ctx.globalCompositeOperation = "destination-out";
}
}
end() {
this.isDown = false;
this.imgData = this.ctx.getImageData(0, 0, this.img.width, this.img.height);
let zeroNum = 0;
this.imgData.data.map((it) => {
if (it === 0) {
zeroNum++;
}
});
let currPst = zeroNum / this.imgData.data.length;
if (this.pst <= currPst) {
if (this.backFun) {
this.backFun();
}
}
}
clean() {
let tempImageData = this.ctx.createImageData(this.imgData);
tempImageData.data.map((it) => {
it = 0;
});
this.ctx.putImageData(tempImageData, 0, 0);
}
}