作者:BLACK595
😎嘿!首先,先来看超酷的效果哦😃!🎨素描图在用户鼠标按下后,就像被施了魔法一样🧙♂️,将鼠标范围内的素描像素神奇地转换成有色像素🌈。
动图无法展示,感兴趣的朋友可以移步: https://juejin.cn/post/7410410146483781673#heading-3
原理
- 设置原图A在底层
- 将模糊过或者另一张图片B覆盖遮挡原图A
- 监听鼠标按下移动事件,抹除B相应部分,露出原图A
也就是橡皮擦
效果,即鼠标点下去移动所经过位置擦除,鼠标松开不清除。
关于绘制图形,图形操作,前端一般都是用Canvas进行处理。 最近抖音豆包AI的插件 豆包MarsCode 也进入了插件市场,咱们拿来用用,提升下速度,自己也可以少敲点代码。
实现
滑动画线
首先,先来实现鼠标按下滑动后画出线条,先来让AI助手来生成下代码。
这里我们必须要把需求描述清楚,要说使用Canvas来实现,不然AI理解不了你要干嘛。 先把代码粘贴进来试下。结果报错了。
onMouseMove
方法重复了,这里它给的代码有点小bug,在引入时引入了onMouseMove
和onMouseUp
,但vue中并没有这两个方法,我们把这两个引入删除。除了这个bug,效果还是可以的。
擦除
现在完成了滑动时画出内容,但是我们需要的是滑动时清除内容,这里就要用到cavas的一个神奇的属性-globalCompositeOperation,该属性定义了我们在绘制图形时如何将新内容
合成现有图形
,合成为新图形。 常用的混合结果如下:
- source-over:默认设置,在现有画布上下文之上绘制新图形。
- source-in:新图形只在新图形和目标画布重叠的地方绘制。其他的都是透明的。
- source-out:在不与现有画布内容重叠的地方绘制新图形。
- destination-over:在现有的画布内容后面绘制新的图形。
- destination-in:现有的画布内容保持在新图形和现有画布内容重叠的位置。其他的都是透明的。
- destination-out:现有内容保持在新图形不重叠的地方。
可以看到,我们需要的效果正是destination-out,画笔划过的地方将原有内容擦除。ctx.globalCompositeOperation = 'destination-out'
填充原图背景
接着我们将原图的背景填充上,先来个灰色背景试试。问问AI,代码少写点
根据它的代码,我们再加上destination-out
的设置,写一个初始化
Canvas的方法init()。
有效像素计算
擦除效果有了后,我们还需要考虑在擦除的时候我们并不需要将全部的的遮挡都擦除,因此需要设置当擦除完大部分的灰色前景后就自动将全部的灰色抹除,也就需要判断当前擦除面积
是否达到一定百分比
。
在Canvas中擦除实际是改变已有图像的透明度,Canvas给我们提供了 getImageData()查看当前图像的像素信息,通过在onMouseMove
中统计图像当前有效像素比
,看是否需要直接清空前景。
有了思路后,让AI给我们生成代码,我们再来看合不合适。
给我们生成了checkAndClearForeground
方法,这里这个方法我们不太清楚,让 豆包MarsCode 给我们注释下。
计算的关键原来在于,在rgba
模式下,一个像素有4个分量,最后一个分量表示透明度,当透明度的分量大于0时,表示这个像素点就是有效的,通过计算有效的像素点就能知道百分比了。
设置背景
有了基本的功能,我们再让UI小姐姐将我们的原图转为素描图,来替换之前的灰色前景。
因为gif帧率的问题,擦除完毕后,清空页面后感觉像变成了白色的,但其实清空后屏幕就透明了。
接着,我们把有色原图设置到Canvas的背景上,这样擦除后,显示的就是有色背景了。
最终效果:
扩展
基于此原理,我们还可以做擦除原本模糊的图像,露出清晰的原图。
或者给前景写上文字后,擦除后露出内容的刮刮卡效果。
在线体验: bulibuli.top:11083/源码地址: (gitee.com)
结尾
有了 豆包MarsCode 帮助我们生成代码后,确实可以减少我们开发的难度和成本,但目前AI给我们的代码也不一定是完全正确的😏,对于部分bug还是需要我们手动去处理。不过当我们有了思路与具体的实现方法后,让AI给我们生成代码后我们就只需要大体看下代码,再改一些参数配置后就能很方便的和我们项目适配,目前AI时代已经来临,我们程序员应该尽快找到一个自己喜欢顺手的AI,辅助开发,加快我们开发效率💪,目前,抖音的 豆包MarsCode也已推出,大家也可以去试试体验一番🎈。