再用Compose Canvas画只猛虎,这次不是封面党
时间:2023-01-30 14:00:00
/ 今日科技快讯 /
最近,针对频繁的网络暴力,抖音进一步提升了平台预防网络暴力的能力。其中,抖音将推出警告功能,拦截不当的私人信息,抖音将推出风险提醒和负内容过滤。
/ 作者简介 /
明天我们将迎来一个快乐的周末。今天再分享一篇文章Compose画虎的文章,这次不是封面党,保证内容与封面一致!
本文由乐翁龙提交,分享Compose绘制一个猛虎,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。
乐翁龙博客地址:
https://juejin.cn/user/1126371661463101/posts
/ 开篇废话 /
但是假期前又有两个需求,忙到昨天终于上线了。当我打开掘金时,我发现每个人都在创造新年,包括烟花、祝福、春联、野兽战斗游戏和老虎画。不要说,‘你有很多金花工作’!我也来参加了。~
写这篇文章是为了看到前端学生使用它Echarts画的老虎:《辞旧迎新 2022 我用Echarts画了一只大老虎,祝大家新年快乐,虎虎生威。(https://juejin.cn/post/7052131692894369)。这只老虎真的可以,所以我也直接拿了。iconfont作者Eve!
实现目标
我们将使用这篇文章Compose的Canvas画一只猛虎,如上动图,如假包换。
关于Compose Canvas不熟悉的同学可以参考我之前写的博客 《Jetpack Compose - Canvas》(https://blog.csdn.net/u010976213/article/details/114638415)Canvas的各种draw()方法主要用于我们这里drawPath()实现方法。
/ 实现流程/
首先,我们需要点击材料 【SVG下载,下载后导入Android Studio:
右键夹在资源文件中,选择Vector Asset导入刚下载的svg文件。
OK,大功告成 ~~~~~~ 了一部分!
让我们来看看生成XML文件主要在其中pathData我们需要利用这些值一步一步地绘制值。那么这些值呢?
1、认识pathData
关于SVG path详情请看Paths – SVG 1.1 (Second Edition)(https://www.w3.org/TR/SVG11/paths.html#PathData)。
我在这里先根据Android写一个简单的pathData,如右侧所示:
接下来,让我们来看看这个神奇的指令:
M0,0l100,0L100,100h100v-100h100v200H0z
M0,0 ,表示path.moveTo(),后面的0,0是坐标位置,所以意思是把画笔移到A(0,0)的位置
l100,0 ,表示path.relativeLineTo(),也就是说,与刚才的A点相比,水平移动100,水平移动0到B点,B的坐标点是(100,0)
L100,100 ,表示path.lineTo(),即绝对移动,直接将画笔移动到(100、100)的位置,因此C的坐标点为(100、100)
h100 ,horizontal,表示path.relativeLineTo()是一种简化版的写法,意思是相对于C点垂直移动100到D点,所以D的坐标是(200,100)。如果用l表示,相当于l100,0”
v-100,vertical,表示path.relativeLineTo(),是一种简化版的写法,意思是相对于D点横向移动100到E点,所以E的坐标是(200,0)
剩下的h、v移动不解释,直接看H:
H0,也是横向移动,但后0表示要移动 x=0 的位置,需要与上文h的相对移动距离区分开。那么从G点直接横向移动到x=因此,H点坐标(0,100)
z ,表示path.close()
通过以上描述,你可能会大致理解pathData所表示的意思。还有一个PathM开头z结尾可以完成。
其实后面还是有比较复杂的。C(三次贝塞尔曲线),Q(二次贝塞尔曲线),A(圆弧)等等,但这里我们就不多介绍了。
以上内容足以让我们画出上面提到的虎。
2、解析pathData
了解到pathData在构成和意义之后,我们可以进行分析并转换Canvas需要的path,然后就可以进行绘制了。
大致描述一下我的临时解决方案,以上规范pathData如果字符是字母,则表示移动moveTo()、lineTo()等命令,后面是坐标,连续坐标可以用空间隔开,处理时要注意。
处理H命令有点特别,因为我们只知道要移动x=0位置,但如果当前位置相对移动,那么我们不知道当前位置的y坐标,所以我们也需要手动计算当前的y坐标,所以我们需要 PathMeasure 类来帮我们处理(谢谢路很长OoO】大佬的指导)。
//由于在compose下PathMeasure没有办法获得位置, //所以我们用android.graphics.PathMeasure(), //然后path也需要转换成android.graphics.Path pathMeasure.setPath(path.asAndroidPath(),false) valposition=FloatArray(2) valtan=FloatArray(2) pathMeasure.getPosTan(pathMeasure.length,position,tan) //至此position存储当前位置坐标
在获得移动命令和坐标后,整体处理变得非常简单,如下所示:
funprocessMethod(){ when(nextMethod){ cmdM->{ path.moveTo(lastX,lastY) } &bsp; cmdm -> {
path.relativeMoveTo(lastX, lastY)
}
cmdL -> {
path.lineTo(lastX, lastY)
}
cmdl -> {
path.relativeLineTo(lastX, lastY)
}
cmdH -> {
//注意此时y坐标应该是当前位置的y坐标
pathMeasure.setPath(path.asAndroidPath(), false)
val position = FloatArray(2)
val tan = FloatArray(2)
pathMeasure.getPosTan(pathMeasure.length, position, tan)
path.lineTo(lastX, position[1])
}
cmdh -> {
path.relativeLineTo(lastX, 0f)
}
cmdV -> {
//注意此时x坐标应该是当前位置的x坐标
pathMeasure.setPath(path.asAndroidPath(), false)
val position = FloatArray(2)
val tan = FloatArray(2)
pathMeasure.getPosTan(pathMeasure.length, position, tan)
path.lineTo(position[0], lastX)
}
cmdv -> {
path.relativeLineTo(0f, lastX)
}
cmdz -> {
path.close()
}
}
}
所以根据上述老虎的SVG图片,从转成的Android pathData我们可以获取到多条path,然后我们按照顺序将其进行绘制,最终就可以得到上述动图了。
说起来很简单,可是在解析pathData以及在绘制老虎的顺序上真真是废了老半天的劲了,一条一条的进行展示、隐藏,看下排序过后的部分数据吧:
最后再看下动图,哇,成果还是可以的吧。画虎点睛,王!!!
【源码已上传GitHub,需要的自取:TigerYear2022】
https://github.com/CooLoongWu/TigerYear2022
推荐阅读:
我的新书,《第一行代码 第3版》已出版!
在微软工作365天,还你一个我眼中更加真实的微软
Jetpack全家桶中最受欢迎的一定是它
欢迎关注我的公众号
学习技术或投稿
长按上图,识别图中二维码即可关注