View绘制系列(9)-Canvas太极图绘制

原创
10/20 08:35
阅读数 3.3K

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角度后所得到的弧 注意:这里传入的startAnglesweepAngle单位均为角度,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)为右下顶点,以rxry为圆角度的圆角矩形,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 注意:这里传入的startAnglesweepAngle单位均为角度,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) 为页面绘制了灰色背景。

往期推荐

View绘制系列(1)-View简介

OpenCV SDK下载及Android Java环境搭建

玩转花式Loading

 

本文分享自微信公众号 - 小海编码日记(gh_1f87b8c00ede)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
1
1 收藏
分享
加载中
这是太极图,不是八卦图
10/21 13:22
回复
举报
哈哈哈哈哈
10/21 13:58
回复
举报
哈哈哈。无情
10/22 09:02
回复
举报
无情+10086
10/25 21:40
回复
举报
莫在意,晓得就成
10/25 21:40
回复
举报
更多评论
打赏
5 评论
1 收藏
1
分享
返回顶部
顶部