刮刮卡demo-canvas實踐

一、利用css將<li><canvas>層重疊;javascript

  • html
<body>
	<div id="wrap">
        <!-- 灰色塗層 -->
		<canvas></canvas>
        <!-- 刮卡結果 -->
		<ul>
			<li></li>
		</ul>
	</div>		
</body>
複製代碼
  • css
<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
			}
			#wrap,ul,ul>li{
				height: 100%;
			}
			ul>li{
				background: url(img/b.png);
				background-size: 100% 100%;
			}
			canvas{
                /* 利用絕對定位讓灰色塗層與刮卡結果重疊 */
				position: absolute;
				left: 0;
				top: 0;
				transition: 1s;
			}
		</style>
複製代碼
  1. 在canvas畫布上繪製刮刮卡圖層圖像;
var canvas = document.querySelector("canvas");
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
if(canvas.getContext){
  var ctx = canvas.getContext("2d")
  var img = new Image()
  img.src = "img/a.png"
  img.onload = function(){
    draw()
}
function draw(){
  var flag = 0  //用於後面統計刮開百分比
  ctx.drawImage(img,0,0,canvas.width,canvas.height)
}
複製代碼

三、在canvas畫布區域監聽鼠標事件或觸摸事件;css

// 監聽鼠標和touch事件
canvas.addEventListener('mousedown', moveStart, false);
canvas.addEventListener('touchstart', moveStart, false);
canvas.addEventListener('mousemove', move, false);
canvas.addEventListener('touchmove', move, false);
canvas.addEventListener('mouseup', moveEnd, false);
canvas.addEventListener('touchend', moveEnd, false);
複製代碼

四、在手指移動過程當中,實時計算手指在畫布中的位置以及移動路徑,利用canvas的globalCompositeOperation方法中的destination-out效果將刮過的地方設置爲透明從而實現刮卡的效果;html

canvas.addEventListener("touchstart",function(ev){
    ev = ev||event;
    var touchC = ev.changedTouches[0];
						
    var x = touchC.clientX - canvas.offsetLeft;
    var y = touchC.clientY - canvas.offsetTop;
    //畫線,解決快速畫圓bug					
    ctx.lineWidth = 40
    ctx.lineCap = "round"
    ctx.lineJoin = "round"
    ctx.globalCompositeOperation="destination-out";

    ctx.save();
    ctx.beginPath();
    ctx.moveTo(x,y)
    ctx.lineTo(x+1,y+1)
    ctx.stroke()
    ctx.restore()
})
canvas.addEventListener("touchmove",function(ev){
    ev = ev||event;
    var touchC = ev.changedTouches[0];
						
    var x = touchC.clientX - canvas.offsetLeft;
    var y = touchC.clientY - canvas.offsetTop;
						
    ctx.save();
    ctx.lineTo(x,y)
    ctx.stroke()
    ctx.restore()
})
複製代碼

五、設置當canvas塗層被刮到必定百分比時去除整個塗層;java

  • 利用canvas的getImageData能夠獲取指定範圍區域的每一個像素點的rgba的信息,其中a指的是透明度,當a爲0時,該像素點徹底透明,當a爲255時,表示該像素點徹底不透明;
  • 經過遍歷指定區域的像素點信息,獲得透明像素點的個數
    • 透明像素點的個數/總像素點的個數=刮開區域所佔百分比
    • 經過設置閾值,使得當所刮區域佔比知足必定值時,刮開整個canvas塗層;
canvas.addEventListener("touchend",function(){
    var imgData = ctx.getImageData(0,0,canvas.width,canvas.height)
    var allPx = imgData.width*imgData.height
    for(var i = 0;i<allPx;i++){
        if(imgData.data[i*4+3]===0){
            flag++
        }
     }
    if(flag>=allPx/2){
        canvas.style.opacity = 0
     }
})					
複製代碼

六、所有刮開之後,刪canvas層canvas

canvas.addEventListener("transitionend",function(){
    this.remove()  //自殺,刪除canvas
})
複製代碼

完整代碼:bash

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
			}
			#wrap,ul,ul>li{
				height: 100%;
			}
			ul>li{
				background: url(img/b.png);
				background-size: 100% 100%;
			}
			canvas{
				position: absolute;
				left: 0;
				top: 0;
				transition: 1s;
			}
		</style>
	</head>
	<body>
		<div id="wrap">
			<canvas></canvas>
			<ul>
				<li></li>
			</ul>
		</div>		
	</body>
	<script type="text/javascript">
		window.onload=function(){
			var canvas = document.querySelector("canvas");
			canvas.width = document.documentElement.clientWidth;
			canvas.height = document.documentElement.clientHeight;
			if(canvas.getContext){
				var ctx = canvas.getContext("2d")
				var img = new Image()
				img.src = "img/a.png"
				img.onload = function(){
					draw()
				}
				function draw(){
					var flag = 0
					ctx.drawImage(img,0,0,canvas.width,canvas.height)
					
					canvas.addEventListener("touchstart",function(ev){
						ev = ev||event;
						var touchC = ev.changedTouches[0];
						
						var x = touchC.clientX - canvas.offsetLeft;
						var y = touchC.clientY - canvas.offsetTop;
						
						ctx.lineWidth = 40
						ctx.lineCap = "round"
						ctx.lineJoin = "round"
						ctx.globalCompositeOperation="destination-out";
						ctx.save();
						
						ctx.beginPath();
						ctx.moveTo(x,y)
						ctx.lineTo(x+1,y+1)
						ctx.stroke()
						ctx.restore()
					})
					
					canvas.addEventListener("touchmove",function(ev){
						ev = ev||event;
						var touchC = ev.changedTouches[0];
						
						var x = touchC.clientX - canvas.offsetLeft;
						var y = touchC.clientY - canvas.offsetTop;
						
						ctx.save();
						ctx.lineTo(x,y)
						ctx.stroke()
						ctx.restore()
					})
					
					canvas.addEventListener("touchend",function(){
						var imgData = ctx.getImageData(0,0,canvas.width,canvas.height)
						var allPx = imgData.width*imgData.height
						for(var i = 0;i<allPx;i++){
							if(imgData.data[i*4+3]===0){
								flag++
							}
						}
						if(flag>=allPx/2){
							canvas.style.opacity = 0
						}
					})
					
					canvas.addEventListener("transitionend",function(){
						this.remove()  //自殺,刪除canvas
					})
				}
			}
		}
	</script>
</html>

複製代碼
相關文章
相關標籤/搜索