在以前的這篇bezierMaker.js——N階貝塞爾曲線生成器的文章中咱們提到了對於高階貝塞爾公式的繪製與生成。不過更多的童鞋看到後可能會不知道其使用場景是什麼。故做者本次分享一下基於bezierMaker.js實現的將靜態圖片按照自定義曲線軌跡扭曲圖片併合稱爲動態效果。html
歡迎關注個人博客,不按期更新中——git
以前的描述可能不是很清楚咱們直接看下效果圖:github
首先加載一張圖:web
而後經過bezierMaker.js提供的試驗場功能來繪製一段曲線,進行圖片扭曲:canvas
最後擬合爲動態圖:數組
再來一個豎直方向的扭動:動畫
demo地址ui
源碼地址url
其中較爲核心的實現即橫向與縱向對一維圖像數據的切分。其中橫向相對簡單,細節以下:spa
如上圖所示,在原始圖像的數據中的數據形式爲一維數組的形式,而對其進行拆分則是一個從中不斷截取與提取數據的過程。橫向拆分較爲簡單,只須要肯定每一行開始的位置便可,截取的數量就是一行的元素數。同時縱向拆分則須要多加一步,咱們須要計算每一層數組中的每個數,像上圖通常拆分第每列數組時首先要遍歷圖的寬獲得每一列的索引,再遍歷圖的高,經過高✖️寬✖️4 + 寬 ✖️ 4算出當前值在原數據中的位置。當拆分紅功數組後,將數組依次移位,移位數爲以前曲線與基準線的偏移量決定。
//pg.js //按行拆分 bezierArr.forEach(function (obj, index) { if (_.imgStartY < obj.y && _.imgStartY + _.imgHeight > obj.y && type === 'row') { var diffX = parseInt(obj.x - _.baseX, 10) //計算偏移量 var dissY = parseInt(obj.y - _.imgStartY, 10) var rowNum = dissY imgDataSlice = _.imgData.data.slice((rowNum) * _.imgWidth * 4, rowNum * _.imgWidth * 4 + _.imgWidth * 4) //按層切片 ... } }) //按列拆分 for (var i = 0; i < _.imgWidth; i++) { imgDataSlice = [] for (var j = 0; j < _.imgHeight; j++) { var index = j * _.imgWidth * 4 + i * 4 var sliceArr = _.imgData.data.slice(index, index + 4) imgDataSlice = imgDataSlice.concat(Array.from(sliceArr)) } if(_.imgChangeObj[i]) { for (var k = 0; k < Math.abs(_.imgChangeObj[i].diffY * 4); k++) { imgDataSlice = _.arraymove(_.imgChangeObj[i].diffY, imgDataSlice) } for (var p = 0; p < imgDataSlice.length / 4; p++) { arr[p * _.imgWidth * 4 + i * 4] = imgDataSlice[p * 4] arr[p * _.imgWidth * 4 + i * 4 + 1] = imgDataSlice[p * 4 + 1] arr[p * _.imgWidth * 4 + i * 4 + 2] = imgDataSlice[p * 4 + 2] arr[p * _.imgWidth * 4 + i * 4 + 3] = imgDataSlice[p * 4 + 3] } } }
核心的數組拆分移位再合併的邏輯相對分散,知道思路便可有興趣的同窗歡迎戳源碼~
核心思想爲從咱們的原始形態到最終態的兩張靜態圖咱們已經獲得了。如今咱們須要作的是添加幾張過渡態。在這裏面有兩種方式:
做者一開始使用了第一種方式,可是有一個明顯的缺陷及經過按比例直接偏移會致使拆分出來的每層的偏移每次都是相同的,那麼就會出現鋸齒現象。由於圖像扭曲可能上一層在這一次移位的時候偏移5合適但是你仍然偏移了總量的1/3致使與下一層的圖像不匹配從而出現鋸齒。故從新選擇了第二種方式,由從新計算各中間態圖像的控制點再來移位圖像數據,圖像的呈現狀況就改善了不少。
因爲操做圖像數據量比較大,故在嘗試demo的時候若是遇到ui卡頓那是正在計算中,並無引入webworker之類的因此請稍等一會就會出現結果=。=
PS:demo使用步驟
慣例po做者的博客,不定時更新中——
有問題歡迎在issues下交流。