一 、前言css
一直在作PC端的前端開發,從互聯網到行業軟件。最近發現移動端已經成爲前端必備技能了,真是不能中止學習。HTML5新增的一些東西,canvas是用的比較多也比較複雜的一個,簡單的入門了一下,經過一個刮獎效果來學習。html
2、canvas基礎前端
本文的目標是作一個刮獎效果,可是若是都不知道canvas是怎麼回事,那麼確定也沒法進行下去,因此先講講canvas基礎吧。android
首先,該怎麼理解canvas,思來想去,最好的理解辦法應該就是把canvas理解爲一個空白的畫紙,一張你能夠在上面畫畫的紙。web
而後,你經過HTML標籤訂義canvas,例如:canvas
<canvas id="canvas" width="200" height="200">你的瀏覽器不支持canvas</canvas>
這樣,你就設置好了一張200×200的畫紙了。瀏覽器
這裏要注意的是,canvas元素的寬高須要直接寫在標籤上或者經過js來設置。若是用css設置,那麼瀏覽器會理解爲把這張紙縮放成你設置的寬高。跟預期仍是不同的。iphone
而後,有了紙第二步就是畫東西了,畫東西須要的就是筆了。獲得畫筆:學習
var ctx = document.getElementById("canvas").getContext("2d");
這樣,就有了這隻筆了,叫ctx。ui
而後就是繪畫,這裏要重點說明的是,canvas畫東西須要兩步
簡單來講,你畫一條直線,那麼代碼應該是告訴系統我要從0,0點到100,100點設置一條路徑,而後用黑色描邊這條路徑。
用代碼來描述我上面的那句話:
ctx.beginPath(); // 開始畫路徑 ctx.moveTo(0, 0); // 移動到0,0點 ctx.lineTo(100, 100); // 畫條直線到100,100點 ctx.closePath(); // 閉合路徑 ctx.lineWidth = "5"; // 設置線寬5px // 至此路徑描述已經結束 ctx.strokeStyle = "#000"; // 設置描邊顏色爲黑色 ctx.stroke(); // 執行描邊
上面代碼就能夠畫一條直線了。固然,canvas能作的遠遠不止這些。
由於是基礎嘛,因此canvas就講到這裏啦。關於canvas的東西太多,但原理基本都是這樣,固然除了描邊,還有填充(fill),填充各類形狀(fillRect),畫圖形(drawImage)等。系統學習canvas確實須要一本書或者一系列教程,由於我也是剛學,就不誤人子弟啦。這些基礎其實也夠理解下面的例子啦。
3、刮獎效果
最簡單的一個刮獎效果原理大概就是這樣,放一張底圖(或者是文字,例如謝謝惠顧呀),而後再它之上覆蓋一個canvas,遮住這張圖,接着綁定touchstart(mousedown),touchmove(mousemove),touchend事件。而後移動的時候用「透明」填充canvas,那麼被canvas遮住的部分就會呈現出來了。
直接看代碼吧,最簡單的實現
1 <!DOCTYPE html> 2 <!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7"><![endif]--> 3 <!--[if IE 7]><html class="no-js lt-ie9 lt-ie8"><![endif]--> 4 <!--[if IE 8]><html class="no-js lt-ie9"> <![endif]--> 5 <!--[if gt IE 8]><!--><html class="no-js"><!--<![endif]--> 6 7 <head> 8 <meta charset="utf-8"> 9 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 10 <title>刮獎</title> 11 <meta name="description" content="刮獎"> 12 <meta name="viewport" content="width=device-width, initial-scale=1"> 13 14 <style> 15 body{margin: 0;} 16 #price{width: 200px; height: 100px; font-size: 40px; color: #f60; line-height: 100px; text-align: center;} 17 #canvas{position: absolute; top: 0; left: 0;} 18 </style> 19 </head> 20 21 <body> 22 23 <div id="price">謝謝惠顧</div> 24 <canvas id="canvas" width="200" height="100">你的瀏覽器不支持canvas</canvas> 25 26 <script> 27 28 // 獲得畫筆 29 var cvs = document.getElementById("canvas"), 30 ctx = cvs.getContext("2d"), 31 touchRadius = 5; // 默認手指觸摸半徑,能夠自定義設置 32 33 // 默認填充灰色來遮住文字 34 ctx.fillStyle = "#ccc"; 35 ctx.fillRect(0, 0, 200, 100); // fillRect,用矩形填充 36 37 // 畫園的方法 38 // @param { integer } 圓心的x座標 39 // @param { integer } 圓心的y座標 40 // @param { integer } 圓心半徑 41 // @param { string } 填充的顏色(本例中會經過其他代碼設置爲‘透明’,因此這個設置能夠忽略) 42 var fillCircle = function (x, y, radius, fillColor) { 43 this.fillStyle = fillColor || "#eee"; 44 this.beginPath(); 45 this.moveTo(x, y); 46 this.arc(x, y, radius, 0, Math.PI * 2, false); // 標準畫圓 47 this.fill(); 48 }; 49 50 // 獲得塗抹的百分比(此處參考了部分他人代碼,出處http://www.cnblogs.com/jscode/p/3580878.html) 51 var getTransparentPercent = function (ctx, width, height) { 52 var imgData = ctx.getImageData(0, 0, width, height), // 獲得canvas的像素信息 53 pixles = imgData.data, 54 transPixs = []; 55 for (var i = 0, j = pixles.length; i < j; i += 4) { // 由於存儲的結構爲[R, G, B, A],因此要每次跳4個長度 56 var a = pixles[i + 3]; // 拿到存儲alpha通道的值 57 if (a === 0) { // alpha通道爲0,就表明透明 58 transPixs.push(i); 59 } 60 } 61 return (transPixs.length / (pixles.length / 4) * 100).toFixed(2); 62 } 63 64 // 綁定事件(此處參考了部分他人代碼,出處http://www.cnblogs.com/jscode/p/3580878.html) 65 // 須要判斷是PC仍是手機 66 var device = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()), 67 clickEvtName = device ? 'touchstart' : 'mousedown', 68 moveEvtName = device ? 'touchmove' : 'mousemove'; 69 70 // 判斷是否是開始觸摸等 71 if (!device) { 72 var isMouseDown = false; 73 document.addEventListener('mouseup', function (e) { 74 isMouseDown = false; 75 }, false); 76 } else { 77 document.addEventListener("touchmove", function (e) { 78 if (isMouseDown) { 79 e.preventDefault(); 80 } 81 }, false); 82 document.addEventListener('touchend', function (e) { 83 isMouseDown = false; 84 }, false); 85 } 86 87 // 開始移動 88 cvs.addEventListener(clickEvtName, function (e) { 89 isMouseDown = true; 90 var x = (device ? e.touches[0].clientX : e.clientX); 91 var y = (device ? e.touches[0].clientY : e.clientY); 92 ctx.globalCompositeOperation = 'destination-out'; // 關鍵部分,描述當在canvas上再次繪畫時候的狀況,這個設置即是以前所說的透明 93 fillCircle.call(ctx, x, y, touchRadius); 94 console.log("當前塗抹比例爲:" + getTransparentPercent(ctx, 200, 100)); 95 }, false); 96 97 // 移動中 98 cvs.addEventListener(moveEvtName, function (e) { 99 if (!device && !isMouseDown) { 100 return false; 101 } 102 var x = (device ? e.touches[0].clientX : e.clientX); 103 var y = (device ? e.touches[0].clientY : e.clientY); 104 ctx.globalCompositeOperation = 'destination-out'; 105 fillCircle.call(ctx, x, y, touchRadius); 106 console.log("當前塗抹比例爲:" + getTransparentPercent(ctx, 200, 100)); 107 }, false); 108 </script> 109 </body> 110 111 </html>
上面的代碼徹底是按照順序來寫的,因此應該很容易看懂的吧。其中關鍵的就是設置透明,還有就是設備的判斷。
Update:增長了一個判斷刮開了多少比例的代碼,由於實際需求極可能是刮開多少就告訴用戶刮獎結束。這裏,由於刮開的部分是「透明的」,在代碼中就是說RGBA顏色值中的A是透明的,經過getImageData方法能夠獲得每一個像素點的RGBA值,而後計算一下比例便可。在控制檯能夠看到刮開的比例數據。
至此,也算是用canva完成了第一個小效果了。
轉載本站文章請註明做者和出處 奇葩一朵朵 – http://www.cnblogs.com/season-huang/ ,請勿用於任何商業用途