锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

再用Compose Canvas画只猛虎,这次不是封面党

时间:2023-01-30 14:00:00 075k1l100只电阻器

b422515137a4878e7612c9127d24e114.png

/ 今日科技快讯 /

最近,针对频繁的网络暴力,抖音进一步提升了平台预防网络暴力的能力。其中,抖音将推出警告功能,拦截不当的私人信息,抖音将推出风险提醒和负内容过滤。

/ 作者简介 /

明天我们将迎来一个快乐的周末。今天再分享一篇文章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全家桶中最受欢迎的一定是它

欢迎关注我的公众号

学习技术或投稿

长按上图,识别图中二维码即可关注

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章