View绘制系列(9)-Canvas太极图绘制
Canvas太极图绘制
前面我们已经学习了Path.quadTo(float x1, float y1, float x2, float y2)
及Path.cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)
方法的使用,但并不是所有的曲线所有的曲线都需要用贝塞尔曲线来描述,毕竟在没有专业软件辅助的情况下,确认控制点也是一件很复杂的事情,比如说我们闭合曲线中包含一段椭圆弧或者圆弧,抑或者圆角矩形,我们该怎么做呢?作为描述组合路径的核心类,Path当然会提供对应的方法。
Path
部分路径截取函数对照说明表:
函数名 | 函数说明 | 备注 |
---|---|---|
addArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle) | 添加以(left ,top )为左上顶点,(right ,bottom )为右下顶点矩形的内切椭圆中,以startAngle 角度起始,划过sweepAngle 角度后所得到的弧 | 注意:这里传入的startAngle 及sweepAngle 单位均为角度,sweepAngle 顺时针为正值,逆时针为负值 |
addArc(RectF oval, float startAngle, float sweepAngle) | 同上,只是将矩形的描述方式改成了RectF 类对象描述 | 同上 |
addCircle(float x, float y, float radius, Direction dir) | 添加一个圆到Path 路径中,dir 说明环绕圆周方向 | 其中dir 取值Direction.CW 为顺时钟,Direction.CCW 为逆时针 |
addOval(float left, float top, float right, float bottom, Direction dir) | 添加一个椭圆到路径中,椭圆是以(left ,top )为左上顶点,(right , bottom )为右下顶点矩形的内切椭圆,dir 说明环绕方向 | 同上 |
addRect(float left, float top, float right, float bottom, Direction dir) | 添加以(left ,top )为左上顶点,(right , bottom )为右下顶点的矩形,dir 说明环绕方向 | 同上 |
addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir) | 添加以(left ,top )为左上顶点,(right , bottom )为右下顶点,以rx ,ry 为圆角度的圆角矩形,dir 说明环绕方向 | 同上 |
arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) | 添加以(left ,top )为左上顶点,(right ,bottom )为右下顶点矩形的内切椭圆中,以startAngle 角度起始,划过sweepAngle 角度后所得到的弧,forceMoveTo 是否强制修正路径起点,如果为true ,相当于执行Path.moveTo (startAngle 对应坐标),随后arcTo | 注意:这里传入的startAngle 及sweepAngle 单位均为角度,sweepAngle 顺时针为正值,逆时针为负值 |
添加整个图形路径的函数原型比较简单,大家自行尝试使用下,这里我们重点演示下addArc
方法的使用。
查看下图,是一个太极图,为了更好的说明问题,我在图上添加了辅助坐标系和点:
从图上我们可以将该图简单分为四部分,黑色小圆M,白色小圆N,以及曲线ABOA(即白色阴阳鱼区域),曲线BAOB(即黑色阴阳鱼区域).
进一步在上图中添加辅助点和辅助曲线,我们可以看到,白色阴阳鱼实际上是由半圆BFA,半圆AEO及半圆BDO的圆周曲线所围成,同理黑色阴阳鱼是由半圆AGB,半圆BDO,及半圆OEA的圆周围成。
假设我们以View
宽度(在onDraw
函数内可以通过getWidth()
,getHeight()
获取View
的可见宽高)为大圆O直径,那么圆M及圆N直径就为getWidth()
/2。
圆O的外接矩形顶点为:
左上顶点:(0,0),右下顶点:(getWidth()
,getHeight()
)
圆M的外接矩形顶点为:
左上顶点:(getWidth()
/4,),右下顶点:(getWidth()
*3/4,getWidth()
/2)
圆N的外接矩形顶点为:
左上顶点:(getWidth()
/4,getWidth()
/2),右下顶点:(getWidth()
*3/4,getWidth()
)
那么左侧白色阴阳鱼的路径为:
Path leftDiagramPath = new Path(); //添加圆O的左侧半圆BFA所在的圆周 leftDiagramPath.addArc(0,0,getWidth(),getWidth(),90,180); //添加圆M的右侧半圆AEO所在的圆周,起始角度负90,以水平X正向为0度 leftDiagramPath.addArc(getWidth()/4,0,getWidth()*3/4,getWidth()/2,-90,180); //添加圆N的左侧半圆ODB所在的圆周,起始角度负90,以水平X正向为0度 leftDiagramPath.addArc(getWidth()/4,getWidth()/2,getWidth()*3/4,getWidth(),-90,-180);
右侧黑色阴阳鱼的路径为:
Path rightDiagramPath = new Path(); //添加圆O的右侧半圆BGA所在的圆周 rightDiagramPath.addArc(0,0,getWidth(),getWidth(),90,-180); //添加圆M的右侧半圆AEO所在的圆周,起始角度负90,以水平X正向为0度 rightDiagramPath.addArc(getWidth()/4,0,getWidth()*3/4,getWidth()/2,-90,180); //添加圆N的左侧半圆ODB所在的圆周,起始角度负90,以水平X正向为0度 rightDiagramPath.addArc(getWidth()/4,getWidth()/2,getWidth()*3/4,getWidth(),-90,-180);
两个小圆的绘制代码,取半径为100:
//上面的黑色小圆圆心 Point topCircleCenter = new Point(getWidth()/2,getWidth()/4); //下面的白色小圆圆心 Point bottomCircleCenter = new Point(getWidth()/2,getWidth()*3/4); //小圆半径 float smallerCircleRadius = 100; canvas.drawCircle(topCircleCenter.x,topCircleCenter.y,smallerCircleRadius,paint); canvas.drawCircle(bottomCircleCenter.x,bottomCircleCenter.y,smallerCircleRadius,paint);
先调用canvas.drawPath(@NonNull Path path, @NonNull Paint paint)
绘制阴阳鱼,随后绘制两个小圆,运行效果如下:
这里我在 onDraw
函数刚开始使用 canvas.drawColor(Color.GREY)
为页面绘制了灰色背景。
往期推荐
本文分享自微信公众号 - 小海编码日记(gh_1f87b8c00ede)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
深挖 Netty 源码:时间轮底层原理分析
本文选自 Doocs 开源社区旗下“源码猎人”项目,作者tydhot[1]。项目将会持续更新,欢迎 Star 关注。项目地址:https://github.com/doocs/source-code-hunter 该文所涉及的 Netty 源码版本为 4.1.6。 HashedWheelTimer 是什么 Netty 的时间轮HashedWheelTimer给出了一个粗略的定时器实现,之所以称之为粗略的实现是因为该时间轮并没有严格的准时执行定时任务,而是在每隔一个时间间隔之后的时间节点执行,并执行当前时间节点之前到期的定时任务。 当然具体的定时任务的时间执行精度可以通过调节 HashedWheelTimer 构造方法的时间间隔的大小来进行调节,在大多数网络应用的情况下,由于 IO 延迟的存在,并不会严格要求具体的时间执行精度,所以默认的 100ms 时间间隔可以满足大多数的情况,不需要再花精力去调节该时间精度。 HashedWheelTimer 的实现原理 HashedWheelTimer 内部的数据结构 private final HashedWheelBucket[] wheel;...
- 下一篇
分享套接字数据包序列化与反序列化方法
分享套接字数据包序列化与反序列化方法 简单说一下,本文不涉及Socket的连接、数据接收,只是对数据包(byte[])的序列化和反序列化方法的封装介绍。 本文目录 本文背景 一般操作 本文操作 总结 1.本文背景 经常做C/S,客户端与服务端通信基本是TCP/UDP通信,套接字用得飞起。 比如我们有一个系统,这个系统又分几个系统子模块进程: C++服务端 Android 客户端 iOS 客户端 WPF桌面管理端 ...... 几个模块之间通过TCP或者UDP通信,数据包解析与组装是常规操作,我们定义数据包格式如下: 一个数据包包含包头和包体,定义如下: 包头 序号 字段名 数据类型 备注 1 消息标识 int 用于标识数据包是否合法 2 名称 string 当前消息名称,用于标识数据包类型 3 版本号 int 当前消息版本号,允许程序中消息存在多个版本,用于版本迭代 包含这三个字段:消息标识、名称、版本号,唯一确定消息对象。 包体 序号 字段名 数据类型 备注 1 字段1 数据类型 字段1 2 字段2 数据类型 字段2 包体直接定义字段信息,就像定义类属性一样。 另包头与包体中数据类型...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- 设置Eclipse缩进为4个空格,增强代码规范