多语言展示
当前在线:1119今日阅读:168今日分享:49

canvas实现相片滤镜功能

利用canvas实现上传本地相片绘制到画布,并且可以对图片进行不同滤镜操作,从而实现相应的滤镜效果,最终效果图如下图。Tips:       除了上传本地相片,也可以直接拍照或拍视频上传;视频需要实现拖动图片并在拖动过程才能看到动态图;       由于篇幅问题,本文只实现了单图操作,也未实现拖动、旋转、拉伸、剪切、拼图等功能,以后有时间再分析其它功能的实现原理。
工具/原料
1

Sublime Text

2

Chrome浏览器调试

编写静态页面

html代码和css样式如下图,这一块比较简单,也不是本文重点,主要说明一下动画keyframes(bounce),这个是利用animation对两个圆形实行先后放大缩小,从而实现加载动画效果;其它代码可自行查看下图。

实现原理
1

由于涉及的函数比较多,先分析基本操作(这一块文章《操作栏弹出框动态效果和视差滚动》有很详细分析,这里主要讲一下作用),详细代码如下图:       第一二段作用是实现点击滤镜列表的关闭按钮(closeBtn),调用函数animatePanel的动态效果,往下隐藏滤镜列表(filters-panel),再往上打开操作栏(control-button);       最后一段作用是“阻止手机滑动时拖动页面”,提高体验感。

2

分析实现过程关联的第一个函数($.imgFliters),该函数封装的是不同滤镜的计算方式,里面总共有20种左右,本文主要分析四种比较常用,其它的实现方法类似,只是更换里面的计算方式;该函数原理就是对getImageData获取的图片像素数据进行循环取数(图片像素数据排列规则r(红) g(绿) b(蓝) a(透明度),每个像素都存在这四方面信息,所以4个为一个间隔),然后利用公式计算,更换r(红)、g(绿)、b(蓝)的值,从而实现不同滤镜效果;详细分析如下:       首先分析一下公共函数loopData,该函数对获取的图片像素数据进行循环获取里面的r(红)、g(绿)、b(蓝)的值,然后把该值传入函数(fn),根据函数调用的计算公式返回r(红)、g(绿)、b(蓝)的值,最后把该值替换原图的r(红)、g(绿)、b(蓝);       最后毛玻璃、连环画、黑白、怀旧四种滤镜都是调用函数loopData,传入两个参数(获取的像素数据imageData和对应的计算公式),该函数实现把获取的像素数据替换为对应滤镜计算公式计算出来的值。Tips:       计算公式都是根据PS方法写出来,都是固定的,这一块可以自行查看下面代码就可以。

3

分析实现过程关联的最后一个函数(drawImageToCanvas),该函数实现把上传的图片(或画布中的图片),根据不同的滤镜方式绘制到画布的对应位置上;主要分析下面几点(详细代码如下图):      获取像素数据之前,图片对象(imgObject)要先load,不然会获取空白数据;      重绘之前(putImageData),需要清除(clearRect)原图,不然会导致卡顿,特别是大图比较明显。

4

实现过程是先利用h5的file进行上传操作,然后获取上传的图片,最后使用函数drawImageToCanvas把图片绘制到画布上面,同时弹出滤镜列表;点击不同滤镜,根据不同滤镜标识值(data-filters),调用函数$.imgFliters对应计算公式替换原图的像素数据,从而实现滤镜效果;主要分析下面几点(详细代码如下图):       获取的图片地址(reader)需要onload,不然会获取空白数据;       点击滤镜图片会弹出加载页面和处理图片,由于js是单线程,大图情况下会导致卡顿,为了使加载页面第一时间出现,使用了定时器(setTimeout),但要注意使用完需要注销,避免性能问题。

推荐信息