En cuanto al contenido de la animación, he escrito varios artículos antes:
Esta sección implementa un efecto de animación de orden de trazos. La idea proviene de la biblioteca de código abierto Hanzi Writer , este es el efecto de su sitio web oficial:
Pero Android no se puede usar directamente, por lo que existe una idea de imitación. Encontré sus datos de origen en esta biblioteca hermana hanzi-writer-data , que es un json,
{"strokes": [], "medians": [], "radStrokes": []}
复制代码
Tome el carácter chino "I" como ejemplo, es así, es desordenado, ¿verdad? Afortunadamente, entiendo un poco el formato SVG:
Entre ellos, el formato SVG es fijo, y cada letra (sin distinción entre mayúsculas y minúsculas) tiene su significado:
- M xy : Indica mover el pincel al punto (x, y), listo para comenzar a dibujar
- L xy: significa
Line to
que el comando L dibujará un segmento de línea a (x, y) - Z:
Z
El comando dibujará una línea recta desde el punto actual hasta el punto de inicio del camino, es decir, un camino cerrado - Q x1 y1, xy : dibujar una curva Bezier de segundo orden a través de un punto de control
- C x1 y1, x2 y2, xy : dibuje una curva bezier cúbica a través de dos puntos de control a (x, y)
Se puede ver que strokes
es un dato SVG de este tipo, medians
y radStrokes
lo exploraremos más adelante, primero strokes
dibuje y vea el efecto.
analizar trazos
Este paso es muy simple, pura sub-pregunta:
- No importa si guarda los datos de origen de hanzi-writer-data en el directorio de activos o en la ruta local
- Analice el carácter chino json en una ruta específica
Pegue el código directamente aquí:
dibujar trazos
El primer problema es que después de obtener los datos SVG, ¿cómo dibujarlos a través de Canvas?
Después de la investigación, se encuentra que el sistema nos PathParser
proporciona una buena interfaz:
// 可以解析 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, los trazos ya se están moviendo. Pero... el efecto que queremos es Hanzi Writer
así , esto obviamente no está a la altura del estándar, no se preocupe, si conoce la capa Canvas, creo que debería tener una idea en este momento.
Animación de orden de trazos
La capa del lienzo no es el foco de esta sección. Si aún no la conoce, puede inventarla.
La idea aquí es crear una capa y mostrar strokes
el efecto medians
mixto de y sobre la capa.
Primero, de acuerdo con el progreso, dibuje todas las rutas de los trazos en el progreso y genere el mapa de bits de la imagen de destino. Aquí, se usa srcMode, lo que significa que solo se conserva la imagen de origen:
Establezca el modo de pincel actual en PorterDuff.Mode.SRC_IN
, lo que significa que la imagen de origen solo se dibuja donde se cruzan la imagen de origen y la imagen de destino:
A continuación, de acuerdo con el progreso, dibuje todos los trazos en el progreso, es decir, la ruta mediana, donde se usa srcMode, lo que significa que solo se conserva la imagen de origen:
Finalmente, restaure el lienzo:
Echa un vistazo al efecto, ¿está bien?
De hecho, es casi, como un trastorno obsesivo-compulsivo, realmente no lo soporto, y me falta un poco.
Arco de inicio de pluma
Como solución, traté de dibujar un pequeño círculo en la posición del primer y último punto de la columna vertebral de cada trazo, y dibujé un pequeño círculo con él como centro, porque la dirección es incierta, el círculo es una buena opción, paga atención para dibujar en el srcCanvas.
Ubicación de datos, como se mencionó anteriormente, medians
tome el primer punto y el último punto de cada trazo en , no se mencionará el método de análisis, consulte la demostración para el código específico.
Cuando dibuje srcBmp, agregue los radianes de inicio y descenso de la pluma, preste atención al índice:
Echa un vistazo al efecto, perfecto:
Bueno, esta sección está aquí, el código se ha subido a github , puedes echarle un vistazo si estás interesado.