日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

前端实现旗帜飘动效果系列 (Ⅲ):canvas2D实现(2)

發布時間:2025/4/16 HTML 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前端实现旗帜飘动效果系列 (Ⅲ):canvas2D实现(2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

? ? ?本講我們在上一講的基礎上,給旗子添加高光,使其看起來更加有立體感。我會用兩種方式來分別實現這個效果,然后比較一下優劣,還是先講原理。

?? ? 方法一:在原來的代碼drawImage之后通過 fillRect 函數來增加一個白色蒙層,通過透明度的遞增和遞減來模擬。具體多少透明度?當然你可以用數學的方法來求導計算出某一點的斜率,根據其大小和正負得出其透明度大小,斜率越大,透明度越小。這里用一種更取巧也效率更高的方法,即保存某一點前一個點的y軸坐標,與該點的y坐標相減,即可得到斜率的相對大小,因為兩點之間的x軸上距離都是1px,所以y軸變化越大,|斜率|則越大。

? ? 方法二:先通過遍歷 getImageData 函數返回的元素逐像素獲取原始畫布每個點的rgba值,然后每一幀通過運動函數對每個點的位置進行偏移,對比原畫布,獲取該點在原位置的rgba值,然后直接對a分量進行修改,修改的依據仍然是斜率。

這是方法一的代碼,我只貼出修改的部分(// +++ 之間):

var y = 0 // +++++++++++++++++++++ var lastY = 0 // +++++++++++++++++++++ var distance = 0 var tick = function () {if (stop) return falsetimeNow = Date.now()delta = timeNow - timeLastif (delta > interval) {timeLast = timeNowdistance += (delta / 1000 * v)ctx.clearRect(0, 0, canvasWidth, canvasHeight)for (var x = 0; x < imgWidth; x++) {y = cftA * x * Math.sin(cftX * (x - distance)) + amplitudectx.drawImage(image, x, 0, 1, imgHeight, x, y, 1, imgHeight)// +++++++++++++++++++++ctx.fillStyle = 'rgba(255,255,255,' + (x === 0 ? 0 : (y - lastY) * 0.5) + ')'ctx.fillRect(x, y, 1, imgHeight)// +++++++++++++++++++++lastY = y}}requestAnimationFrame(tick) }

完整代碼戳這里

Demo:See the Pen?flag waving by canvas2d(rect) ?by Kay (@oj8kay) on?CodePen.

方法二的核心代碼如下:

var tick = function () {if (stop) return falsetimeNow = Date.now()delta = timeNow - timeLastif (delta > interval) {timeLast = timeNowdistance += (delta / 1000 * v)// +++++++++++++++++++++for (var i = 0; i < canvasHeight; i++) {for (var j = 0; j < canvasWidth; j++) {if (i === 0) {yBuf[j] = cftA * j * Math.sin(cftX * (j - distance))}r = (i * canvasWidth + j) * 4g = r + 1b = r + 2a = r + 3oR = r + (~~(0.5 + yBuf[j])) * canvasWidth * 4oG = oR + 1oB = oR + 2oA = oR + 3offset = j === 0 ? 0 : (yBuf[j] - lastY) * 100pixels[r] = oPixels[oR] + offsetpixels[g] = oPixels[oG] + offsetpixels[b] = oPixels[oB] + offsetpixels[a] = oPixels[oA]lastY = yBuf[j]}}ctx.putImageData(imgData, 0, 0)// +++++++++++++++++++++}requestAnimationFrame(tick) }

這個方法做出的另外一點修改是,由于操作是對畫布逐像素進行的,包括透明元素,所以既不用clearRect,也不用對Y軸進行偏移。

完整代碼戳這里

Demo:See the Pen?flag waving by canvas2d(pixel) ?by Kay (@oj8kay) on?CodePen.

兩個方法的效果圖如下

通過chrome dev tool對兩者的性能進行分析:

這是方法1的CPU占有率的變化:

這是方法2的:

哪個性能更好顯而易見。方法二的性能雖然差,但是它的好處是靈活性更大,你甚至可以任意改變“光源”的位置。

? ?下一講我會通過webgl對其進行重寫,使其大部分的渲染邏輯從CPU轉到GPU,可以使其的性能得到成倍的提高。建議大家先學習一下webgl的一些基本用法,包括矩陣的知識,著色器等。

轉載于:https://my.oschina.net/codingDog/blog/1839099

總結

以上是生活随笔為你收集整理的前端实现旗帜飘动效果系列 (Ⅲ):canvas2D实现(2)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。