当前位置:网站首页>自定义 View 实现汉字笔顺动画
自定义 View 实现汉字笔顺动画
2022-07-30 02:30:00 【锐湃】
关于动画的内容,之前也写过几篇:
本节来实现一个笔顺动画的效果。思路来自开源库 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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
边栏推荐
- Type-C边充电边OTG芯片——LDR6028A
- Successfully resolved pydotplus.graphviz.InvocationException: GraphViz's executables not found
- Mysql中事务是什么?有什么用?
- 基于低能耗自适应聚类层次结构(LEACH)(Matlab代码实现)
- fluttter学习之ButtonStyle 、MaterialStateProperty
- matlab洗碗机节水模型的优化设计-这是个课题名称,不是买洗碗机,审核的人仔细看下,谢谢
- Oracle数据库表空间整理回收与释放操作
- win11 自带远程桌面使用(包含非局域网使用以及win11升级为专业版)
- Docker一键安装MySQL
- The box office broke 790 million US dollars. Have you watched this recent dinosaur movie?
猜你喜欢
随机推荐
绘制概率密度图
五种绑定彻底弄懂this,默认绑定、隐式绑定、显式绑定、new绑定、箭头函数绑定详解
Google浏览器打开axure产品原型的解决方案
Not enough information to list load addresses in the image map. (STM32 compilation error)
奥比中光高级副总裁王兆民离职 董事会秘书暂未取得资格证
Mysql中事务是什么?有什么用?
Docker一键安装MySQL
Leetcode.19 删链表倒数第 N 个结点(栈/先后指针)
Detailed explanation of carousel picture 2 - carousel pictures through left positioning
综合设计一个OPPO页面--返回顶部使用--使用链接的锚点a+id
绘图问题记录
【ModelArts系列】华为ModelArts训练yolov3模型(训练管理)
【机器学习】通俗易懂决策树(原理篇)
RAII技术学习
华宝新能通过注册:拟募资近7亿 营收增加利润反而下降
菜刀、冰蝎、蚁剑、哥斯拉的流量特征
Zero code tools recommended - HiFlow
JS Bom location 楼层导航效果 offsetTop data-n 方括号选择器
测试/开发程序员面试该如何谈薪资待遇呢?突破这个坎......
【笔记】结巴分词绘制词云图








