在以前的这篇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下交流。