关于动画的内容,之前也写过几篇:
本节来实现一个笔顺动画的效果。思路来自开源库 Hanzi Writer ,这是它官网的效果:
但 Android 不能直接用,也就有了模仿下的想法。我在这个姐妹库里 hanzi-writer-data,找到了它的源数据,是一个 json,
{"strokes": [], "medians": [], "radStrokes": []}
复制代码
以汉字 “我” 为例,是这样的,很乱是吧,幸亏我对 SVG 格式有丢丢了解:
其中,SVG 格式都是固定的,每个字母(不区分大小写)都有它的含义:
- M x y : 表示移动画笔到 (x, y) 点,准备开始绘制
- L x y : 代表
Line to
, L 命令将会画一条线段到 (x, y) - Z :
Z
命令会从当前点画一条直线到路径的起点,即闭合路径 - Q x1 y1, x y : 通过一个控制点绘制二阶贝塞尔曲线
- C x1 y1, x2 y2, x y : 通过两个控制点绘制三次贝塞尔曲线到 (x, y)
可以看出 strokes
就是这样一个 SVG 数据,至于 medians
和 radStrokes
我们稍后再探,先将 strokes
绘制出来看下效果。
解析strokes
这步很简单,纯送分题:
- 将 hanzi-writer-data 源数据,保存到 assets 目录,或本地路径,都没所谓
- 将特定路径下汉字 json 解析出来
这里直接贴下代码吧:
绘制strokes
首先就遇到问题,拿到 SVG 数据后,要怎么通过 Canvas 绘制呢?
研究后发现,系统 PathParser
为我们提供好了接口,直接就能办到这件事:
// 可以解析 SVG 数据, 生成绘制所需要的 Path
PathParser.createPathFromPathData(String pathData)
复制代码
代码是这样的,拿到汉字笔画的 path 集合:
这样一来,我们就可以直接在 draw(Canvas)
接口中绘制了,
运行,发现并没有正常显示出来。经过排查,是因为 hanzi-writer-data
提供的源数据,绘制出来是上下翻转的,而且大小默认 1024 * 1024px, 所以在绘制的时候,我们需要将 y 轴翻转并等比缩放,来看下代码吧:
再运行,看下效果:
完美。但这是静态的,怎么能像 Hanzi Writer
这样动起来呢?
探究medians
在源数据 json 内的 medians
,这是干嘛的?
我们将 medians
解析出来,主要代码见下,medians 是解析出来的 path 集合:
在上文的 draw(Canvas)
方法中绘制出来:
效果见下:
可以猜测每个 path array 其实就是汉字的一个笔画,为了验证是否正确,我将每个笔画 array 的第一个 point 坐标都点了出来,来看下效果,是这样的:
至此,我们应该知道 medians
的含义了。
动起来
现在为止,我们已经知道了 每个汉字的笔画 和 组成笔画的若干骨干点。想动起来,是不是只需要按默认顺序绘制笔画就行了,为了更平滑的效果,我们可以在每个骨干点间进行差值动画。
说干就干,这是属性动画差值:
创建一个 PathMeasure
集合来存储 path, 目的是拿到路径长度和截取路径,具体就不在这里展开说了:
最后根据进度值,在 draw(Canvas)
方法内绘制即可,其中 temp 的作用是,将截取出来的路径,保存到 temp 内:
来看下效果:
ok,笔画已经动起来了。但是..我们想要的效果是 Hanzi Writer
那样的,这个明显不达标啊,别急,如果你对 Canvas 图层有了解,我相信,你此时应该有思路了。
笔顺动画
canvas layer 不是本节的重点,如果你还不了解,可以去补下。
在这里的思路,就是创建一个图层,在图层上显示strokes
与 medians
混合后的效果。
首先根据进度,绘制进度内的所有 stroke path,生成目标图像 bitmap,这里采用 srcMode,代表只保留源图像:
设置当前画笔 mode 为 PorterDuff.Mode.SRC_IN
,表示只在 源图像 和 目标图像 相交的地方绘制源图像:
接下来,根据进度,绘制进度内的所有笔画,即 median path,这里采用 srcMode,代表只保留源图像:
最后恢复画布即可:
来看下效果,是不是很 ok 了:
其实还差点,作为强迫症实在忍受不了,起笔落笔缺失了点..
起笔落笔弧度
作为解决方案,我尝试着在每个笔画的第一个和最后一个骨干点的位置,以其为中心绘制个小圆,因为指向方向不定,圆是个很好的选择,注意要绘制在 srcCanvas。
数据位置,上面已经说了,取 medians
内的每个笔画的第一个点和最后一个点,解析方法就不说了,具体代码去看 demo 吧。
在绘制 srcBmp 时候,将起笔和落笔弧度添加上,注意索引:
来看下效果,完美:
好了,本节就到到这里了,代码都上传到了 github ,感兴趣的可以看下。
参考资料
作者:Zuo
链接:https://juejin.cn/post/7103192601515425823
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。