移動(dòng)端刮刮樂的實(shí)現(xiàn)方式(js+HTML5)
程序員有一種慣性思維,就是看見一些會(huì)動(dòng)的東西(帶點(diǎn)科技含量的,貓啊,狗啊就算了),總要先想一遍,這玩意用代碼是怎么控制的。比如電梯,路邊的霓虹燈,遙控器,小孩子的玩具等。
有時(shí)候還會(huì)感覺程序員看世界會(huì)看的透徹一點(diǎn).............
想必大家都玩過(guò)刮刮樂,下面就介紹一種刮刮樂的移動(dòng)端實(shí)現(xiàn)方式!用到canvas
1、用HTML 5 canvas globalCompositeOperation 屬性實(shí)現(xiàn)刮刮樂
思路:
(1)首先需要一個(gè)盒子定位,確定刮刮樂區(qū)域想要放在哪里
(2)定位盒子里有個(gè)放內(nèi)容的盒子,也就是放獎(jiǎng)品的
(3)用一個(gè)畫布(canvas)把上面的盒子蓋住
(4)當(dāng)手觸摸移動(dòng)的時(shí)候,可以擦除部分畫布,露出獎(jiǎng)品區(qū)
(5)當(dāng)擦除足夠多(3/4)的時(shí)候,可以選擇讓畫布自動(dòng)消失,慢慢淡出(這個(gè)效果選做)
主要是第四步,如何擦除?
這里選用 globalCompositeOperation,即Canvas中的合成操作。簡(jiǎn)單來(lái)說(shuō),Composite(組合),就是對(duì)你在繪圖中,后繪制的圖形與先繪制的圖形之間的組合顯示效果,比如在國(guó)畫中,你先畫一筆紅色,再來(lái)一筆綠色,相交的部分是一種混色,而在油畫中,綠色就會(huì)覆蓋掉相交部分的紅色,這在程序繪圖中的處理就是Composite,Canvas API中對(duì)應(yīng)的函數(shù)就是globalCompositeOperation。
globalCompositeOperation中有個(gè)屬性值是“destination-out",也就是當(dāng)繪畫重疊時(shí)顯示透明。剛好用到這里,我們就可以在畫布上亂畫,畫過(guò)的地方就是重疊的地方,就會(huì)變成透明,然后露出畫布下的東西,也就是我們想要的效果。
html 代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <title></title> <link rel="stylesheet" type="text/css" href="css/guaguale.css" rel="external nofollow" /> </head> <body> <!-- 大的背景盒子--> <div id="main"> <!-- 定位的盒子--> <div class="canvasBox"> <!-- 放內(nèi)容的盒子--> <span id="prize"> 恭喜發(fā)財(cái),紅包拿來(lái) </span> <!-- 蒙版畫布--> <canvas id="canvas"></canvas> </div> </div> </body> <script type="text/javascript"> var canvas = document.getElementById("canvas"); var ctx = canvas.getContext('2d'); /* 畫布偏移量,下面用到的時(shí)候再介紹*/ var arr = getOffset(canvas); var oLeft = arr[0]; var oTop = arr[1]; /* 初始化畫布*/ ctx.beginPath(); ctx.fillStyle = '#ccc'; ctx.fillRect(0,0,canvas.width,canvas.height); ctx.closePath(); /* 增加觸摸*/ document.addEventListener("touchstart",function(){ /* 初始化畫筆*/ ctx.beginPath(); /* 畫筆粗細(xì)*/ ctx.lineWidth = 30; /* 設(shè)置組合效果*/ ctx.globalCompositeOperation = 'destination-out'; /* 移動(dòng)畫筆原點(diǎn)*/ ctx.moveTo(event.touches[0].pageX-oLeft,event.touches[0].pageY-oTop); },false) document.addEventListener("touchmove",function(){ /* 根據(jù)手指移動(dòng)畫線,使之變透明*/ ctx.lineTo(event.touches[0].pageX-oLeft,event.touches[0].pageY-oTop); /* 填充*/ ctx.stroke(); }) /* 之所以會(huì)用到下面的那個(gè)函數(shù)getOffset(obj) * 是因?yàn)閑vent.touches[0].pageX、pageY獲取的是相對(duì)于可視窗口的距離 * 而lineTo畫筆的定位是根據(jù)畫布位置定位的 * 所以就要先獲取到畫布(canvas)相對(duì)于可視窗口的距離,然后計(jì)算得出觸摸點(diǎn)相對(duì)于畫布的距離 * */ /* 獲取該元素到可視窗口的距離*/ function getOffset(obj){ var valLeft = 0,valTop = 0; function get(obj){ valLeft += obj.offsetLeft; valTop += obj.offsetTop; /* 不到最外層就一直調(diào)用,直到offsetParent為body*/ if (obj.offsetParent.tagName!='BODY') { get(obj.offsetParent); } return [valLeft,valTop]; } return get(obj); } </script> </html>
css代碼如下:
*{ margin: 0; padding: 0; } #main{ width: 100%; padding: 20px 0; background-color: red; } .canvasBox{ width: 78%; height: 160px; border-radius: 10px; background-color: #FFF; margin-left: 11%; line-height: 160px; text-align: center; position: relative; } #canvas{ width: 96%; height: 96%; position: absolute; left: 2%; top: 2%; background-color: transparent; }
第五步要用到canvas像素點(diǎn)的獲取(這塊注意,像素級(jí)操作,要在服務(wù)器環(huán)境下打開)
getImageData(int x,int y,int width,int height):該方法獲取canvas上從(x,y)點(diǎn)開始,寬為width、高為height的圖片區(qū)域的數(shù)據(jù),該方法返回的是一個(gè)CanvasPixelArray對(duì)象,該對(duì)象具有width、height、data等屬性。data屬性為一個(gè)數(shù)組,該數(shù)組每4個(gè)元素對(duì)應(yīng)一個(gè)像素點(diǎn)。
(對(duì)圖片的反相操作也可以這樣做,改變r(jià)gba值)
getImageData(int x,int y,int width,int height)返回的對(duì)象,data里面存儲(chǔ)的是像素點(diǎn)信息
我們?cè)俅蛴ata,data屬性為一個(gè)數(shù)組,每4個(gè)元素對(duì)應(yīng)一個(gè)像素點(diǎn)(以rgba的形式保存每一個(gè)像素點(diǎn)的信息)。
所以我們就可以根據(jù)像素點(diǎn)的opcity值來(lái)判斷這個(gè)像素點(diǎn)是不是透明,是不是等于0?
透明的像素點(diǎn)數(shù)量/總像素點(diǎn)數(shù)量 = 擦除比例
js代碼:
document.addEventListener("touchend",function(){ /* 獲取imageData對(duì)象*/ var imageDate = ctx.getImageData(0,0,canvas.width,canvas.height); /* */ var allPX = imageDate.width * imageDate.height; var iNum = 0;//記錄刮開的像素點(diǎn)個(gè)數(shù) for(var i=0;i<allPX;i++){ if(imageDate.data[i*4+3] == 0){ iNum++; } } if(iNum >= allPX*3/4){ // disappear里面寫了緩慢清除的css3動(dòng)畫效果 canvas.setAttribute('class','disappear'); } },false)
" .disappear " 的css樣式,css3消失動(dòng)畫
.disappear{ -webkit-animation: disa 2s 1; animation: disa 2s 1; -webkit-animation-fill-mode: forwards; -moz-animation-fill-mode: forwards; -o-animation-fill-mode: forwards; animation-fill-mode: forwards; } @keyframes disa{ 0%{opacity:1;} 100%{opacity: 0;} }
相對(duì)比網(wǎng)上的其他一些實(shí)現(xiàn)方式,這種還是比較簡(jiǎn)單的一種,大家相互學(xué)習(xí)。有什么其他的辦法可以留言相互學(xué)習(xí)
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
webpack4.0打包優(yōu)化策略整理小結(jié)
這篇文章主要介紹了webpack4.0打包優(yōu)化策略整理小結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03基于JS實(shí)現(xiàn)9種不同的面包屑和分布式多步驟導(dǎo)航效果
本文是小編給大家分享的基于js實(shí)現(xiàn)的9種不同風(fēng)格的面包屑和分布式多步驟導(dǎo)航效果,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-02-02用JS實(shí)現(xiàn)根據(jù)當(dāng)前時(shí)間隨機(jī)生成流水號(hào)或者訂單號(hào)
本文通過(guò)實(shí)例代碼給大家介紹了基于JS實(shí)現(xiàn)根據(jù)當(dāng)前時(shí)間隨機(jī)生成流水號(hào)或者訂單號(hào)的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05解決layui使用layui-icon出現(xiàn)默認(rèn)圖標(biāo)的問(wèn)題
今天小編就為大家分享一篇解決layui使用layui-icon出現(xiàn)默認(rèn)圖標(biāo)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09node.js chat程序如何實(shí)現(xiàn)Ajax long-polling長(zhǎng)鏈接刷新模式
node.js chat是node.js作者用JS寫的一個(gè)多人聊天工具, 源代碼公開下載,網(wǎng)址是chat.nodejs.org。作者用這個(gè)小例子,來(lái)展示如何用nodejs開發(fā)高效率的應(yīng)用程序。對(duì)于nodejs的學(xué)習(xí)者來(lái)說(shuō),是一個(gè)很好的例子2012-03-03微信小程序?qū)W習(xí)筆記之目錄結(jié)構(gòu)、基本配置圖文詳解
這篇文章主要介紹了微信小程序?qū)W習(xí)筆記之目錄結(jié)構(gòu)、基本配置,結(jié)合實(shí)例形式詳細(xì)分析了微信小程序的相關(guān)注冊(cè)、配置及基本使用方法,并配以圖片加以說(shuō)明,需要的朋友可以參考下2019-03-03JavaScript動(dòng)態(tài)加載重復(fù)綁定問(wèn)題
這篇文章主要介紹了JavaScript動(dòng)態(tài)加載重復(fù)綁定問(wèn)題,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-04-04JavaScript全屏和退出全屏事件總結(jié)(附代碼)
這篇文章主要介紹了JavaScript全屏和退出全屏事件,先通過(guò)window.ieIsfSceen = false或true進(jìn)行判斷是否為全屏,在進(jìn)行進(jìn)入全屏和退出全屏的操作,需要的朋友可以參考下2017-08-08JavaScript頁(yè)面模板庫(kù)handlebars的簡(jiǎn)單用法
本文主要是給大家分享的一個(gè)javascript頁(yè)面模板庫(kù)Handlebars的簡(jiǎn)單用法,可以幫助大家輕松的構(gòu)建語(yǔ)義化模板,非常的實(shí)用,推薦給大家。2015-03-03Typescript文件被識(shí)別為視頻的問(wèn)題解決
這篇文章主要為大家介紹了Typescript文件被識(shí)別為視頻的問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06