canvas合并图片,canvas图像处理
之前访问cssdesignawards的时候,发现了一个分割图片内容的效果(网址:https://weareludwig.com)。可以点进去看看。感觉挺爽的,就自己试着实现了一下,效果还不错。效果视图https://codepen.io/geeknoble/pen/OQaOVG
分析
首先我们可以发现,图片的内容被分成了小矩形,每个矩形都是随机平移的。画布的drawImage函数可以把图片内容裁剪出来,绘制到画布上,所以这个效果的主要实现原理就是使用drawImage。主要有两个作用,一个是打乱和还原画面内容,一个是和下一个画面切换。这两种效果都可以使用drawImage,只是移动的距离不同。有了整体思路,就可以开始实现了。
初始工作
首先,我们需要初始化一些变量,如图片的宽度和高度,矩形的数量,切割尺寸等。然后计算每个矩形的坐标,并使用双循环将矩形坐标保存在数据中。每个矩形都有一个随机位移,也需要保存和存储在randoms中。其中x,y表示画布canvas的坐标,x1,y1表示图片裁剪的坐标。
init: function(上下文,宽度,高度,面积,img){ this . context=context;this.img=imgthis.imgWidth=img[0]。宽度;//图像宽度和高度this.imgeight=img [0]。身高;this . index=0;//当前图片序号this.width=width//画布宽度和高度this.height=heightthis . area=height/12;//小矩形长度this . countx=width/this . area;//水平和垂直方向的小矩形个数this . county=height/this . area;this . wx=this . img width/this . countx;//小矩形this . wy=this.imgeight/this.county; this . state=true中图片的宽度和高度;//图片状态,true表示这个. this.dataFlag=true//小直角坐标状态,true表示不添加随机值this.duration=1000//动画时间this.duration2=1500this . start time=0;this . data=[];//小直角坐标信息this . randoms=[];//位置随机值//初始化直角坐标var x1=0,y1=0,x=0,y=0;for(var I=0;我这个县长;I){ for(var j=0;j this.countXj){ context . draw image(this . img[this . index],x1,y1,this.wx,this.wy,x,y,this.area,this . area);//存储直角坐标this.data.push ({x1: x1,y1: y1,x: x,y:y });//添加随机值this . random . push(random(-this . area,this . area));x1=this.wxx=this.area} x1=0;y1=this.wyx=0;y=this.area} this . check margin();}检测边缘
在给矩形添加位移之前,我们需要判断位移后的坐标是否超出了图片的边界。例如,如果顶部的矩形在Y轴上移动,它只能向上移动。判断条件是当前坐标加位移值是小于0还是大于图片的宽度和高度。如果更新后的坐标小于0,那么随机值一定是负数,需要改成正数。如果它大于图像高度,可以将其更改为负数。因为每个矩形都向一个方向移动,所以我在这里写下偶数位移动X轴,奇数位移动Y轴。
//检测边缘检查margin:function(){ var self=this;这个。数据。foreach(function(item,index) { if (index % 2==0) { //下标为2的倍数时移动x轴,否则移动y轴如果(项。x1自我。randoms[index]0)//改为正数自我。randoms[index]=-self。randoms[索引];如果(项。x1自我。wx自我。randoms[index]self。图像宽度)//改为负数自我。randoms[index]=-数学。ABS(自我。randoms[index])} else { if(item。y1自我。randoms[index]0)self。randoms[index]=-self。randoms[索引];如果(项。y1自我。randoms[index]selfwy自我。imgheight)自我。randoms[index]=-数学。ABS(自我。randoms[index])})}分离和复原
动画的内容的分离和复原就是更新矩形坐标的值,打乱内容只要将数据里的坐标加上随机值,而复原就是减去随机值,
//检测边缘检查margin:function(){ var self=this;这个。数据。foreach(function(item,index) { if (index % 2==0) { //下标为2的倍数时移动x轴,否则移动y轴如果(项。x1自我。randoms[index]0)//改为正数自我。randoms[index]=-self。randoms[索引];如果(项。x1自我。wx自我。randoms[index]self。图像宽度)//改为负数自我。randoms[index]=-数学。ABS(自我。randoms[index])} else { if(item。y1自我。randoms[index]0)self。randoms[index]=-self。randoms[索引];如果(项。y1自我。randoms[index]self。wy自我。imgheight)自我。randoms[index]=-数学。ABS(自我。randoms[index])})}在储存好坐标后就可以去实现平移动画了,移动的过程有一个平滑的过渡,我们可以使用Tween.js的缓动算法,该算法有四个参数分别是当前时间,初始位置,结束位置,动画时间。详细内容可以参考张鑫旭的这篇文章https://www。张新旭。com/WordPress/2016/12/how-use-tween-js-animation-easing/。通过Tween.js可以算出每一帧要移动的距离,然后再使用requestAnimationFrame去更新坐标。
块动画:function(){ var flag=1;if (this.state) { //判断是打乱图片还是还原图片这个。update(true)} else { flag=-1;这个。更新(假);} var self=这个;这个。开始时间=新日期();//获取当前时间this.state=!这个州;(函数动画(){ var t=new Date();if(t=自我。开始时间本身。持续时间){//动画结束条件返回false}自我。数据。foreach(function(item,index){ if(index % 2==0){ var pos=math。吐温。世博会。easeinout(t-self。开始时间,0,self.randoms[index] * flag,self。持续时间);//计算出每帧移动的距离自我。语境。画图像(自我。img【自己。index],item.x1 pos,item.y1,self.wx,self.wy,item.x,item.y,self.area,self。面积);} else { var pos=math。吐温。世博会。easeinout(t-self。开始时间,0,self.randoms[index] * flag,self。持续时间);自我。语境。画图像(自我。img【自己。index],item.x1,item.y1 pos,self.wx,self.wy,item.x,item.y,self.area,self。面积);} });requestAnimationFrame(动画);})();}到这里就已经实现了分离和复原的动画了
图片切换
接下来,我们开始处理图片切换的部分,有点像旋转木马。轮播动画是将每张图片的位置移动可视窗口的宽度,这里也一样。您可以通过将坐标添加到图片的高度来打开Y轴。与旋转木马不同的是,我们这里只有一个帆布标签。切换时,我们只需要改变当前图片和下一张图片的坐标。当前图片的移动距离是y1 pos,下一张图片的移动距离是y1 pos-imgHeight(为什么要减少imgHeight?).
//垂直滑动动画垂直动画:function (val) {if(!this.time2) {返回false} this . check time(2);var self=this瓦尔。val=1:val=-1;//判断是向上滑动还是向下滑动if((this . index val)0 (this . index val)=(this . img . length)){//判断图片序号是否返回false} this.state?this . update(true):this . update(false);this . start time=new Date();(函数动画(){ var t=new Date();if(t=self . start time self . duration 2){ val===1?self . index:self . index-;//调整图片顺序self.index 0?self . index=self . img . length-1:self . index;self.index=self.img.length?self . index=0:self . index;返回false} self . data . foreach(function(item){ var pos=math . tween . cubic . easeinout(t-self . start time,0,(self.imgHeight) * val,self . duration 2);//更新当前图片坐标self . context . draw image(self . img[self . index],item.x1,item。Y1pos,self.wx,self.wy,item.x,item.y,self.area,self . area);//更新下一张图片的坐标,self . context . draw image(self . img[self . index val],item.x1,item.y1 pos-self.image * val,self.wx,self.wy,item.x,item.y,self.area,self . area);});requestAnimationFrame(动画);})()} X轴的切换也是如此。现在所有功能都差不多完成了,可以在codepen中查看完整的代码。
这就是本文的全部内容。希望对大家的学习和支持有帮助。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。