最近專案剛好用到這種效果,也就是有點像刮刮卡一樣,在行動裝置上,把某張圖片刮掉顯示出另一張圖片。效果圖如下:
DEMO請戳右:DEMO
# #這種在網路上還蠻常見的,本來就想直接上網找個demo套用下他的方法就行了,套用了才發現,在android上卡出翔了,因為客戶要求,在android不要求特別流暢,至少要能玩,但網路上找的那個demo實在太卡,根本就是沒辦法玩的情況。於是就想自己寫一個算了,本文也就權當記錄研究過程。
這種刮圖的效果,首先想到就是用HTML5的canvas來實現,而canvas的API中,可以清除像素的就是clearRect方法,但是clearRect方法的清除區域矩形,畢竟大部分人的習慣中的橡皮擦都是圓形的,所以就引入了剪輯區域這個強大的功能,也就是clip方法。用法很簡單:
ctx.save() ctx.beginPath() ctx.arc(x2,y2,a,0,2*Math.PI); ctx.clip() ctx.clearRect(0,0,canvas.width,canvas.height); ctx.restore();
上面那段程式碼就實現了圓形區域的擦除,也就是先實作一個圓形路徑,然後把這個路徑作為剪輯區域,再清除像素就行了。有個注意點就是需要先保存繪圖環境,清除完像素後要重置繪圖環境,如果不重置的話以後的繪圖都是會被限制在那個剪輯區域中。
擦除效果有了,現在就是寫滑鼠移動擦除的效果了,下面我都用滑鼠來描述,因為行動端也差不多,就是把mousedown換成touchstart, mousemove換成touchmove,mouseup換成touchend、以及取得座標點由e.clientX換成e.targetTouches[0].pageX而已。
實作滑鼠移動擦除,剛開始就是想到滑鼠移動時在觸發的mousemove事件中對滑鼠所在位置進行圓形區域擦除,寫出來後發現,當滑鼠移動速度很快的時候,擦除的區域就不連貫了,就會出現下面這種效果,這顯然不是我們想要的橡皮擦擦除效果。
# 既然所有點不連貫,那接下來要做的事就是把這些點連貫起來,如果是實現畫圖功能的話,就可以直接透過lineTo把兩點之間連接起來再繪製,但是擦除效果中的剪輯區域要求要是閉合路徑,如果是單純的把兩個點連起來就無法形成剪輯區域了。然後我就想到用計算的方法,算出兩個擦除區域中的矩形四個端點座標來實現,也就是下圖中的紅色矩形:
計算方法也很簡單,因為可以知道兩個剪輯區域連線兩個端點的座標,又知道我們要多寬的線條,矩形的四個端點座標就變得容易求了,所以就有了下面的程式碼:
var asin = a*Math.sin(Math.atan((y2-y1)/(x2-x1))); var acos = a*Math.cos(Math.atan((y2-y1)/(x2-x1))) var x3 = x1+asin;var y3 = y1-acos; var x4 = x1-asin; var y4 = y1+acos; var x5 = x2+asin;var y5 = y2-acos; var x6 = x2-asin;var y6 = y2+acos;
x1、y1和x2、y2就是兩個端點,從而求出了四個端點的座標。這樣一來,剪輯區域就是圈加矩形,程式碼組織起來就是:
hastouch = "ontouchstart" window?:= hastouch?"touchstart":"mousedown"= hastouch?"touchmove":"mousemove"= hastouch?"touchend":"mouseup"= hastouch?e.targetTouches[0].pageX:e.clientX-= hastouch?e.targetTouches[0].pageY:e.clientY-0,2*0,0= hastouch?e.targetTouches[0].pageX:e.clientX-= hastouch?e.targetTouches[0].pageY:e.clientY- asin = a*Math.sin(Math.atan((y2-y1)/(x2-x1))); acos = a*Math.cos(Math.atan((y2-y1)/(x2-x1))) x3 = x1+ y3 = y1- x4 = x1- y4 = y1+ x5 = x2+ y5 = y2- x6 = x2- y6 = y2+0,2*0,00,0==
如此一來,滑鼠擦除的效果就實現了,不過還有一個要實現的點,就是大部分擦除的效果,當你擦了一定數量的像素後,就會自動把所有圖片內容呈現出來,這個效果,我是用imgData來實現的。程式碼如下:
var imgData = ctx.getImageData(0,0,canvas.width,canvas.height); var dd = 0; for(var x=0;x<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/194/b3254365e902d656c3d36935a2f0dd1c-3.jpg?x-oss-process=image/resize,p_40" class="lazy" Data.width;x+=1){ for(var y=0;y<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/194/b3254365e902d656c3d36935a2f0dd1c-3.jpg?x-oss-process=image/resize,p_40" class="lazy" Data.height;y+=1){ var i = (y*imgData.width + x)*4; if(imgData.data[i+3] > 0){ dd++ } } }if(dd/(imgData.width*imgData.height)<0.4){ canvas.className = "noOp"; }
取得到imgData,對imgData裡的像素進行遍歷,然後再對imgData的data數組裡的rgba中的alpha進行分析,也就是分析透明度,如果像素被擦除了,那麼透明度就是0了,也就是把當前畫布中透明度不為0的像素的數量跟畫布總像素數進行比較,如果透明度不為0 的像素數比例低於40%,那說明目前畫布上就以後有百分六十以上的區域被擦除了,就可以自動呈現圖片了。
此处注意,我是把检查像素这段代码方法mouseup事件里面的,因为这个计算量相对来说还是不小,如果用户狂点鼠标,就会狂触发mouseup事件,也就是会疯狂的触发那个循环计算像素,计算量大到阻塞进程,导致界面卡住的情况,缓解办法如下:加个timeout,延迟执行像素计算,而在每一次点击的时候再清除timeout,也就是如果用户点击很快,这个计算也就触发不了了,还有一个提升的办法就是抽样检查,我上面的写法是逐个像素检查,逐个像素检查的话像素量太大,肯定会卡的,所以可以采用抽样检查,比如每隔30个像素检查一次,修改后的代码如下:
timeout = setTimeout(function(){ var imgData = ctx.getImageData(0,0,canvas.width,canvas.height); var dd = 0; for(var x=0;x<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/194/b3254365e902d656c3d36935a2f0dd1c-3.jpg?x-oss-process=image/resize,p_40" class="lazy" Data.width;x+=30){ for(var y=0;y<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/194/b3254365e902d656c3d36935a2f0dd1c-3.jpg?x-oss-process=image/resize,p_40" class="lazy" Data.height;y+=30){ var i = (y*imgData.width + x)*4; if(imgData.data[i+3] >0){ dd++ } } } if(dd/(imgData.width*imgData.height/900)<0.4){ canvas.className = "noOp"; } },100)
这样就可以较大限度的防止用户狂点击了,如果有其他更好的检查方法欢迎给出意见,谢谢。
到了这一步就都写完了,然后就是测试的时候了,结果并不乐观,在android上还是卡啊卡啊,所以又得另想办法,最终发现了绘图环境中的globalCompositeOperation这个属性,这个属性的默认值是source-over,也就是,当你在已有像素上进行绘图时会叠加,但是还有一个属性是destination-out,官方解释就是:在源图像外显示目标图像。只有源图像外的目标图像部分才会被显示,源图像是透明的。好像不太好理解,但是其实自己测试一下就会发现很简单,也就是在已有像素的基础上进行绘图时,你绘制的区域里的已有像素都会被置为透明,直接看张图更容易理解:
globalCompositeOperation属性效果图解。
有了这个属性后,就意味着不需要用到clip,也就不需要用sin、cos什么的计算剪辑区域,直接用条粗线就行了,这样一来就能够很大限度的降低了计算量,同时减少了绘图环境API的调用,性能提升了,在android上运行应该也会流畅很多,下面是修改后的代码:
hastouch = "ontouchstart" window?:= hastouch?"touchstart":"mousedown"= hastouch?"touchmove":"mousemove"= hastouch?"touchend":"mouseup"= hastouch?e.targetTouches[0].pageX:e.clientX-= hastouch?e.targetTouches[0].pageY:e.clientY-= "round"= "round"= a*2= "destination-out"1,0,2* imgData = ctx.getImageData(0,0 dd = 0( x=0;x<imgData.width;x+=30( y=0;y<img Data.height;y+=30 i = (y*imgData.width + x)*4(imgData.data[i+3] alt="詳解HTML5實現橡皮擦的擦除效果的範例程式碼(圖)" > 0++(dd/(imgData.width*imgData.height/900)<0.4){ canvas.className = "noOp"= hastouch?e.targetTouches[0].pageX:e.clientX-= hastouch?e.targetTouches[0].pageY:e.clientY-==
擦除那部分代码就这么一点,也就相当于画图功能,直接设置line属性后通过lineTo进行绘制线条,只要事前把globalCompositeOperation设成destination-out,你所进行的一切绘制,都变成了擦除效果。鼠标滑动触发的事件里面代码也少了很多,绘图对象的调用次数减少了,计算也减少了,性能提升大大滴。
改好代码后就立即用自己的android机子测试了一下,果然如此,跟上一个相比,流畅了很多,至少达到了客户要求的能玩的地步了。
以上是詳解HTML5實現橡皮擦的擦除效果的範例程式碼(圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

H5帶來了多項新功能和能力,極大提升了網頁的互動性和開發效率。 1.語義化標籤如、增強了SEO。 2.多媒體支持通過和標籤簡化了音視頻播放。 3.Canvas繪圖提供了動態圖形繪製工具。 4.本地存儲通過localStorage和sessionStorage簡化了數據存儲。 5.地理位置API便於開發基於位置的服務。

HTML5帶來了五個關鍵改進:1.語義化標籤提升了代碼清晰度和SEO效果;2.多媒體支持簡化了視頻和音頻嵌入;3.表單增強簡化了驗證;4.離線與本地存儲提高了用戶體驗;5.畫布與圖形功能增強了網頁的可視化效果。

HTML5的核心特性包括語義化標籤、多媒體支持、離線存儲與本地存儲、表單增強。 1.語義化標籤如、等,提升代碼可讀性和SEO效果。 2.和標籤簡化多媒體嵌入。 3.離線存儲和本地存儲如ApplicationCache和LocalStorage,支持無網絡運行和數據存儲。 4.表單增強引入新輸入類型和驗證屬性,簡化處理和驗證。

H5提供了多種新特性和功能,極大地增強了前端開發的能力。 1.多媒體支持:通過和元素嵌入媒體,無需插件。 2.畫布(Canvas):使用元素動態渲染2D圖形和動畫。 3.本地存儲:通過localStorage和sessionStorage實現數據持久化存儲,提升用戶體驗。

H5和HTML5是不同的概念:HTML5是HTML的一個版本,包含新元素和API;H5是基於HTML5的移動應用開發框架。 HTML5通過瀏覽器解析和渲染代碼,H5應用則需要容器運行並通過JavaScript與原生代碼交互。

HTML5的關鍵元素包括、、、、、等,用於構建現代網頁。 1.定義頭部內容,2.用於導航鏈接,3.表示獨立文章內容,4.組織頁面內容,5.展示側邊欄內容,6.定義頁腳,這些元素增強了網頁的結構和功能性。

HTML5和H5沒有區別,H5是HTML5的簡稱。 1.HTML5是HTML的第五個版本,增強了網頁的多媒體和交互功能。 2.H5常用於指代基於HTML5的移動網頁或應用,適用於各種移動設備。

HTML5是超文本標記語言的最新版本,由W3C標準化。 HTML5引入了新的語義化標籤、多媒體支持和表單增強,提升了網頁結構、用戶體驗和SEO效果。 HTML5引入了新的語義化標籤,如、、、等,使網頁結構更清晰,SEO效果更好。 HTML5支持多媒體元素和,無需第三方插件,提升了用戶體驗和加載速度。 HTML5增強了表單功能,引入了新的輸入類型如、等,提高了用戶體驗和表單驗證效率。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。