像梦一样奔驰|Vue + Canvas 实现流畅的钢笔涂鸦效果

疫情期间 , 小朋友们都采用远程教育的方式 , 其中有项涂鸦的功能 , 看着那不流畅的画笔 , 就有点怪难受的 , 就想着自己鼓捣一下 。 动手前 , 我曾考虑采用类似 Konva 这样的三方类库 , 但结合自身的需求 , 说不定后续会有更多的个性化需求呢 , 综合评定后还是选择了徒手撸 Canvas 来实现 , 要定制 Konva 等三方类库又麻烦 , 还是用 Canvas 从零开始吧 。
准备开始前 , 我去体验了谷歌的涂鸦白板 , Apache 的 OpenMeeting(功能齐全 , UI 较为陈旧) , 以及小画桌 , 还有腾讯 / 网易的相关涂鸦白板 。 不得不说 , 谷歌的涂鸦白板 , 画出来的线条 , 真不是一般的顺滑 , 还附带了各种笔刷效果 。 想着自己要实现这样的功能了 , 虽然谷歌的涂鸦白板没有开源代码 , 但效果总有楷模了 , 还是可以尽量靠拢 , 多借鉴借鉴的 。
像梦一样奔驰|Vue + Canvas 实现流畅的钢笔涂鸦效果最终的实现效果
本文说的要实现钢笔效果 , 而在此之前 , 我已经实现了一种笔刷效果 , 即马克笔 。 该笔刷的实现较为简单些 , 具体实现可以看看《Canvas 实现流畅的画笔》
要实现钢笔的效果 , 我们得想想怎么模拟现实中钢笔写出来的效果 , 因为是针对 WEB 端的 , 力度方面无法获取 , Pointer 拿到的力度值是不变的 , 我主要针对速度方面做了处理 , 其它方面未做处理 。
对于速度的处理 , 我们可以尝试定义笔刷粗细在某个范围内 , 鼠标移动速度越快 , 笔刷就越细小 , 越慢就越粗 。 也就是说 , 我们可以记录坐标点生成的时间 , 比对两个坐标点的时间差来判定速度的快慢 , 再根据定义的粗细范围来确定笔刷粗细 。 这相对也符合我们写字时的状态 , 速度快 , 笔锋转 , 画出来的线条就细 。 虽然看起来不似毛笔那般复杂 , 提笔写的时候 , 各种中锋 , 侧锋 , 露锋等 。 话不多说 , 既然有了想法 , 我们来尝试实现一下简单的钢笔涂鸦效果 。
准备绘制鼠标按下 , 记录当前坐标点 , 生成临时画布(离屏渲染)并设置临时画布默认属性 。
像梦一样奔驰|Vue + Canvas 实现流畅的钢笔涂鸦效果准备绘制
绘制过程1. 调用 Point 基类 , 生成坐标
2. 获取记录数组中的最后一个坐标点数据
3. 计算两个坐标点之间的距离(如果距离过小 [ 我默认设置为5px ] , 则不进行绘制操作)
像梦一样奔驰|Vue + Canvas 实现流畅的钢笔涂鸦效果绘制过程
创建贝塞尔曲线实例1. 记录坐标 points(保证该字段内有且仅有3个坐标点) 。
2. 第1个坐标点 , 直接采用绘制原点操作 , 该方法内直接略过 。
3. 因第1个坐标点已绘制成圆点 , 故第2个坐标点时 , 也直接略过 。
4. 第3个坐标点进入 , 准备开始生成贝塞尔曲线类的实例 。
5. 为了保证第1个坐标点与第2个坐标点的绘制连贯性 , 将强制插入第1个坐标点数据进 points 数组 , 新生成的数组 , 下标往后延1位 。
6. 最后将插入数据的清除即可 。
像梦一样奔驰|Vue + Canvas 实现流畅的钢笔涂鸦效果创建贝塞尔曲线实例
计算笔刷粗细值根据两坐标点之间的距离及其生成时记录的时间点 , 获取移动速度值 , 再根据该值来确定笔刷粗细值 。
像梦一样奔驰|Vue + Canvas 实现流畅的钢笔涂鸦效果计算笔刷粗细值