最近有在看canvas的一些東西,以前在手機端看過有些活動頁面可以實現在手機端刮獎效果,就類似刮彩票顯示中獎的效果,然後自己想了一下要怎麼實現。實現原理是用canvas遮擋住中獎的結果,然後再原來的canvas層繪製透明效果讓底部的中獎結果實顯示出來。
具體主要的canvas api如下:
詳情參考: canvas API
關鍵參數是這個 globalCompositeOperation 這個參數設置對了纔可以實現透明繪製效果,具體參考上面的API接口文檔。
代碼如下:
<!DOCTYPE html>
<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7"><![endif]-->
<!--[if IE 7]><html class="no-js lt-ie9 lt-ie8"><![endif]-->
<!--[if IE 8]><html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--><html class="no-js"><!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="./index.css" disabled>
<title>刮獎</title>
<meta name="description" content="刮獎">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body{margin: 0;padding:0;}
.canvas-box {position:relative;width:200px;height:200px;}
#canvas{position:absolute;left:0;z-index:99;}
.word {position:absolute;left:0;width: 200px; height: 100px;line-height:100px;text-align:center;font-size:16px;}
</style>
</head>
<body>
<div class="canvas-box">
<canvas id="canvas" width="200" height="100"></canvas>
<div class="word">一等獎</div>
</div>
</body>
<script>
const reusult = ['一等獎', '二等獎', '三等獎', '四等獎', '謝謝惠顧'];
let startFill = false; // 鼠標按鈕開始塗抹效果標識
let canvasDom = document.querySelector('#canvas'); // canvas元素
let canvasDomX = canvasDom.getContext("2d"); // 畫板
let touchRadius = 15; // 默認手指觸摸半徑,可以自定義設置
// 繪製遮擋層
let setCanvas = () => {
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#ccc";
ctx.fillRect(0,0,200,100);
};
let setResult = (elem) => {
let randomNum = Math.floor(Math.random() * 5);
document.querySelector(elem).innerHTML = reusult[randomNum];
};
// 得到塗抹的百分比
let getTransparentPercent = function (ctx, width, height) {
var imgData = ctx.getImageData(0, 0, width, height), // 得到canvas的像素信息
pixles = imgData.data,
transPixs = [];
for (var i = 0, j = pixles.length; i < j; i += 4) { // 因爲存儲的結構爲[R, G, B, A],所以要每次跳4個長度
var a = pixles[i + 3]; // 拿到存儲alpha通道的值
if (a === 0) { // alpha通道爲0,就代表透明
transPixs.push(i);
}
}
// 全部的帶透明度和不帶透明度計算比例
return (transPixs.length / (pixles.length / 4) * 100).toFixed(2);
}
// 繪製塗擦效果圓形
// @param { integer } 圓心的x座標
// @param { integer } 圓心的y座標
// @param { integer } 圓心半徑
// @param { string } 填充的顏色(本例中會通過其餘代碼設置爲‘透明’,所以這個設置可以忽略)
let fillCircle = function (x, y, radius, fillColor) {
this.fillStyle = fillColor || "#eee";
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false); // 標準畫圓
this.fill();
};
let int = () => {
setResult('.word'); // 隨機設置中獎的結果
setCanvas(); // 繪製畫布遮擋住底部中獎結果
// 鼠標按下監聽
canvasDom.addEventListener('mousedown', function(e) {
startFill = true;
let x = e.clientX;
let y = e.clientY;
canvasDomX.globalCompositeOperation = 'destination-out'; // 設置繪製時透明效果可以看到底部中獎結果
fillCircle.call(canvasDomX, x, y, touchRadius, '#ccc');
}, false);
// 鼠標移動監聽
canvasDom.addEventListener('mousemove', function(e) {
if (startFill) {
let x = e.clientX;
let y = e.clientY;
canvasDomX.globalCompositeOperation = 'destination-out';
fillCircle.call(canvasDomX, x, y, touchRadius, '#ccc');
let percent = getTransparentPercent(canvasDomX, 200, 100);
console.log("當前塗抹比例爲: " + percent + " %");
// 塗抹超過50%提示中獎信息
if (percent > 50) {
alert('您的中獎信息爲:' + document.querySelector('.word').innerHTML);
startFill = false;
document.location.reload();
}
}
}, false);
// 鼠標彈起監聽
canvasDom.addEventListener('mouseup', function(e) {
startFill = false;
}, false);
};
// 頁面初始化
int();
</script>
</html>
運行結果: