自定义View学习笔记08—Path基本操作
2017-12-27 18:08
387 查看
从本篇笔记开始,我们进入上一篇笔记里面提到的大杀器Path的世界。
同样的,我们依循惯例先来看看Path的常用方法(API21以下的):
同样的,使用到Path,也要关闭硬件加速。方法同前。
Path作用
之所以称Path是一个大杀器,并单独来学习,就是因为Path不仅能够绘制简单图形,也可以绘制这些比较复杂的图形。另外,根据路径绘制文本和剪裁画布都会用到Path。在2D绘图中基本离不开Path。
Path含义
Path封装了由直线和曲线(二次,三次贝塞尔曲线)构成的几何路径。你能用Canvas中的drawPath来把这条路径画出来(同样支持Paint的不同绘制模式),也可以用于剪裁画布和根据路径绘制文字。我们有时会用Path来描述一个图像的轮廓,所以也会称为轮廓线(轮廓线仅是Path的一种使用方法,两者并不等价)。
另外路径有开放和封闭的区别。开放路径:没有首位相接形成封闭区域;封闭路径:首尾相接形成了一个封闭区域。
Path使用详解
第1组: lineTo、moveTo、 setLastPoint和 close
lineTo:是指从某个点到参数坐标点之间连一条线,这里的某个点就是上次操作结束的点,如果没有进行过操作则默认点为坐标原点。
依照惯例我们先看看API提供的方法:
就是指指从某个点到参数坐标点之间连一条线,这里的“某个点”指的是默认的点(如坐标原点或者上一次操作划线的点),如下:
这里我们调用了两次lineTo,第一次由于之前没有过操作,所以默认点就是坐标原点左上角(这里是View的左上角),结果就是坐标原点到A(100,24)之间连直线。
第二次lineTo,由于我们已经操作过一次了,所以这次的起点就是上一次操作过的终点(100,24),其结果就是绘制了一条从坐标(100,24)到(520,550)的点:
这里我们以常见的图表为例做进一步的学习:
在onDraw()方法里面调用上述方法,运行结果如下:
moveTo 和 setLastPoint:
依照惯例,我们先看下API提供的方法:
这两个方法是完全不相同的
现在用代码来区别:
在onDraw()方法里面分别调用上述方法,二者运行效果如下:
moveTo运行效果:
setLastPoint运行效果
close:
依照惯例,我们先看下API提供的方法:
主要作用是:用于连接当前最后一个点和最初的一个点(如果两个点不重合的话),形成一个封闭的图形。
在onDraw()方法里面调用上述方法,运行效果如下:
注意:
close的作用是封闭路径,与连接当前最后一个点和第一个点,形成封闭图形。如果连接了最后一个点和第一个点仍然无法形成封闭图形,则close什么 也不做。
第2组: addXxx、arcTo
主要作用是在Path中添加基本图形,重点区分addArc与arcTo。
第一类addXxx(基本形状)方法预览:
这一类就是在path中添加一个基本形状,基本形状部分和前面所讲的绘制基本形状并无太大差别,使用上都是通过path.addXxx的方式调用,最后再通过canvas.drawPath()的方法绘制图形,如下:
在onDraw方法中调用上方法,运行效果如下:
方法中的参数含义都应该能理解到,这里重点讲解Path.Direction,Direction的意思是方向、趋势,包含两个枚举常量:
至于对闭合顺序到底有啥影响,图形的渲染等问题等请慢慢看下去。
a、先研究确定CW的闭合顺序的问题,添加一个矩形试试看:
在onDraw方法中调用上方法,运行效果如下:
b、再确定CCW的闭合顺序的问题,添加一个矩形试试看:
在onDraw方法中调用上方法,运行效果如下:
运行结果一模一样,感觉很神奇,并且,你他妈的都一模一样还弄两个出来搞毛啊,消遣人么?其实这个东东是自带隐身技能的,想要让它现出原形,就要用到咱们刚刚学到的setLastPoint(重置当前最后一个点的位置)。
在addRxxCCW()方法中的canvas.drawPath(rectPath, mPaint);之前再加一行代码:rectPath.setLastPoint(-250, 250);运行结果如下,可以明显看到,图形发生了奇怪的变化
需要注意的是,交换坐标点的顺序可能就会影响到某些绘制内容哦,例如上面的例子,你可以尝试交换两个坐标点,或者指定另外两个点来作为参数,虽然指定的是同一个矩形,但实际绘制出来是不同的————参数中点的顺序很重要!参数中点的顺序很重要!参数中点的顺序很重要!一定要记得,重要的事情说三遍。
第二类(Path)方法预览:
第一个方法相对比较简单,也很容易理解,就是将两个Path合并成为一个;
第二个方法比第一个方法多出来的两个参数是将src进行了位移之后再添加进当前path中;
第三个方法是将src添加到当前path之前先使用Matrix进行(矩阵)变换。难度一个个的增大。
下面我们用哪个代码来做演示:
在onDraw方法中调用上方法,运行效果如下:
第三类(addArc与arcTo) 方法预览:
addArc与arcTo的区别:
其中参数的含义如下:
特别注意:
sweepAngle取值范围是 [-360, 360),当 >= 360 或者 < -360 时将不会绘制任何内容, 对于360,你可以用一个接近的值替代,例如: 359.99。
forceMoveTo作用: 是否使用moveTo强制将变量移动到圆弧的起点位移。
addArc ()示例:
在onDraw方法中调用上方法,运行效果如下:
arcTo ()示例:
在onDraw方法中调用上方法,运行效果如下:
第3组:isEmpty、 isRect、isConvex、 set 、offset:
这一组比较简单,稍微说一下就可以了。
isEmpty()方法预览:
log输出结果: com.sloop.canvas E/1: true;;com.sloop.canvas E/2: false
isRect()方法预览:
log 输出结果:
com.sloop.canvas E/Rect: isRect:true| left:0.0| top:0.0| right:400.0| bottom:400.0
set()方法预览:
运行结果如下:
offset()方法预览:
这个的作用就是对path进行一段平移,它和Canvas中的translate作用很像,但Canvas作用于整个画布,而path的offset只作用于当前path。第二个方法的dst参数是存储平移后的path的: dst不为空, 将当前path平移后的状态存入dst中,不会影响当前path; dst为空(null),平移将作用于当前path,相当于第一种方法。
运行结果如下:
第4组: rXxx方法,该方法整体上来讲就是利用相对坐标编程。
rXxx方法的坐标使用的是相对位置(基于当前点的位移),而之前方法的坐标是绝对位置(基于当前坐标系的坐标)。最前面的r就是RelativeLayout的缩写。
使用如下:
onDraw方法里面利用上述方法啊,运行结果如下:
此处仅以 rLineTo 为例,只要理解 “绝对坐标” 和 “相对坐标” 的区别,其他方法类比即可。
布尔操作(API19):
布尔操作与我们中学所学的集合操作非常像,只要知道集合操作中的子集,交集,并集,差集,补集等操作,那么理解布尔操作也是很容易的。
布尔操作是两个Path之间的运算,主要作用是用一些简单的图形通过一些规则合成一些相对比较复杂,或难以直接得到的图形。
布尔运算的核心:布尔逻辑,它有五种逻辑,如下:
在Path中的布尔运算有两个方法:
两个方法中的返回值用于判断布尔运算是否成功,它们使用方法如下:
对 path1 和 path2 执行布尔运算,运算方式由第二个参数指定,运算结果存入到path1中。
如太极中的阴阳鱼,如果用贝塞尔曲线制作的话,可能需要六段贝塞尔曲线才行,而在这里我们可以用四个Path通过布尔运算得到,而且会相对来说更容易理解一点。
这里我就用画阴阳鱼来演示布尔操作:
onDraw方法里面利用上述方法啊,运行结果如下:
Path的基本操作到此结束。
同样的,我们依循惯例先来看看Path的常用方法(API21以下的):
同样的,使用到Path,也要关闭硬件加速。方法同前。
Path作用
之所以称Path是一个大杀器,并单独来学习,就是因为Path不仅能够绘制简单图形,也可以绘制这些比较复杂的图形。另外,根据路径绘制文本和剪裁画布都会用到Path。在2D绘图中基本离不开Path。
Path含义
Path封装了由直线和曲线(二次,三次贝塞尔曲线)构成的几何路径。你能用Canvas中的drawPath来把这条路径画出来(同样支持Paint的不同绘制模式),也可以用于剪裁画布和根据路径绘制文字。我们有时会用Path来描述一个图像的轮廓,所以也会称为轮廓线(轮廓线仅是Path的一种使用方法,两者并不等价)。
另外路径有开放和封闭的区别。开放路径:没有首位相接形成封闭区域;封闭路径:首尾相接形成了一个封闭区域。
Path使用详解
第1组: lineTo、moveTo、 setLastPoint和 close
lineTo:是指从某个点到参数坐标点之间连一条线,这里的某个点就是上次操作结束的点,如果没有进行过操作则默认点为坐标原点。
依照惯例我们先看看API提供的方法:
public void lineTo (float x, float y)
就是指指从某个点到参数坐标点之间连一条线,这里的“某个点”指的是默认的点(如坐标原点或者上一次操作划线的点),如下:
Path mPath = new Path(); Path.lineTo(100,24); Path.lineTo(520,550);
这里我们调用了两次lineTo,第一次由于之前没有过操作,所以默认点就是坐标原点左上角(这里是View的左上角),结果就是坐标原点到A(100,24)之间连直线。
第二次lineTo,由于我们已经操作过一次了,所以这次的起点就是上一次操作过的终点(100,24),其结果就是绘制了一条从坐标(100,24)到(520,550)的点:
这里我们以常见的图表为例做进一步的学习:
private void drawLineTo(Canvas canvas, Paint mPaint){ //默认起始点为上次操作结束的点或者坐标原点(屏幕或者控件的左上角)。 //如下,做了canvas.translate(10, hei-10)之后,默认点为(10, hei-10)处。 canvas.drawColor(Color.parseColor("#dfdfdf")); canvas.translate(10, hei-10); //准备数据 float[] x = {100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600}; float[] y = {24, 150, 380, 73, 400, 220, 245, 280, 350, 465, 500}; List<PathCanvasBean> pathList = new ArrayList<>(); for (int i = 0; i < x.length; i++) { pathList.add(new PathCanvasBean(x[i], y[i]*(-1))); } //绘制折线 mPaint.setStrokeWidth(4); //线冒样式(相当于给原来的直线末端加上一个帽子):圆形,方块,无; //http://blog.csdn.net/harvic880925/article/details/51010839 mPaint.setStrokeCap(Paint.Cap.SQUARE); //设置线段连接处过渡样式:锐角过渡(尖锐的意思),圆弧过渡,直线过渡; mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setColor(Color.parseColor("#93A5F4")); Path mPath = new Path(); //设置折线的起点位置,否则折线起点是系统默认的左上角或者View的左上角。 mPath.moveTo(pathList.get(0).getX(), pathList.get(0).getY()); for (int i = 0; i < x.length; i++) { mPath.lineTo(pathList.get(i).getX(), pathList.get(i).getY()); canvas.drawPath(mPath, mPaint); } float textSize = 12; mPaint.setAntiAlias(true); mPaint.setColor(Color.BLACK); mPaint.setTextSize(textSize); mPaint.setStrokeWidth(1); //cirPaint用于画每段线段之间的点 Paint cirPaint = new Paint(); cirPaint.setAntiAlias(true); cirPaint.setStyle(Paint.Style.FILL_AND_STROKE); cirPaint.setColor(Color.WHITE); for (int i = 0; i < x.length; i++) { //绘制折线转折出的点 int x = pathList.get(i).getX(); int y = pathList.get(i).getY(); canvas.drawCircle(x, y, 5, cirPaint); String coordinate = "(" + x + ", " + y*(-1) + ")"; //绘制每个点对应的坐标值,至于为什么这里要分别加10和textSize/2, //掌握了上一篇笔记“自定义View学习笔记07—Canvas绘制文字”的都应该知道 canvas.drawText(coordinate, x + 10, y + textSize/2, mPaint); } }
在onDraw()方法里面调用上述方法,运行结果如下:
moveTo 和 setLastPoint:
依照惯例,我们先看下API提供的方法:
public void moveTo (float x, float y); public void setLastPoint (float dx, float dy);
这两个方法是完全不相同的
现在用代码来区别:
//moveTo的用法 private void drawMoveTo(Canvas canvas, Paint mPaint){ Path mPath = new Path(); mPath.moveTo(50, 50); mPath.lineTo(500,60); mPath.moveTo(180,160); mPath.lineTo(520,550); canvas.drawPath(mPath, mPaint); //moveTo:移动起点到:x, y; //含义解说:mPath.moveTo(50, 50):折现起点/原点, // mPath.lineTo(500,60):从起点/原点划线到(500,60); //然后将绘图起点移到【mPath.moveTo(180,160)】(180,160), //再从(180,160)划线到(520,550)【mPath.lineTo(520,550)】; } //setLastPoint的用法 private void drawLastPoint(Canvas canvas, Paint mPaint){ Path mPath = new Path(); mPath.moveTo(50,50); mPath.lineTo(100,24); mPath.setLastPoint(200,320); mPath.lineTo(500,580); canvas.drawPath(mPath, mPaint); //setLastPoint是重置上一次操作的最后一个点,在执行完第一次的lineTo的时候, // 最后一个点是A(100,24),而setLastPoint更改最后一个点为C(300,220), // 所以在实际执行的时候,第一次的lineTo就不是从原点O到A(100,24)的连线了, // 而变成了从原点(50,50)到C(200,320)之间的连线。然后再从(200,320)划线到(500,580) }
在onDraw()方法里面分别调用上述方法,二者运行效果如下:
moveTo运行效果:
setLastPoint运行效果
close:
依照惯例,我们先看下API提供的方法:
public void close ()
主要作用是:用于连接当前最后一个点和最初的一个点(如果两个点不重合的话),形成一个封闭的图形。
private void drawClose(Canvas canvas, Paint mPaint){ Path closePath = new Path(); closePath.moveTo(50,50); closePath.lineTo(120, 260); closePath.lineTo(300,400); closePath.lineTo(500,300); closePath.lineTo(400,500); closePath.close(); canvas.drawPath(closePath, mPaint); }
在onDraw()方法里面调用上述方法,运行效果如下:
注意:
close的作用是封闭路径,与连接当前最后一个点和第一个点,形成封闭图形。如果连接了最后一个点和第一个点仍然无法形成封闭图形,则close什么 也不做。
第2组: addXxx、arcTo
主要作用是在Path中添加基本图形,重点区分addArc与arcTo。
第一类addXxx(基本形状)方法预览:
// 第一类(基本形状) public void addCircle(float x,float y,float radius,Path.Direction dir) // 圆形 public void addOval(RectF oval, Path.Direction dir)//椭圆 public void addRect(float left,float top,float right,float bottom, Path.Direction dir)//矩形 public void addRect(RectF rect, Path.Direction dir)//矩形 public void addRoundRect(RectF rect,float[]radii,Path.Direction dir)//圆角矩形 public void addRoundRect(RectF rect,float rx,float ry,Path.Direction dir)//圆角矩形
这一类就是在path中添加一个基本形状,基本形状部分和前面所讲的绘制基本形状并无太大差别,使用上都是通过path.addXxx的方式调用,最后再通过canvas.drawPath()的方法绘制图形,如下:
private void drawRect(Canvas canvas, Paint mPaint){ canvas.translate(wid / 2, hei / 2); Path rectPath = new Path(); rectPath.addCircle(0, 0, 100, Path.Direction.CCW);//圆 RectF rect = new RectF(-200,-200, 200, 200);//矩形 rectPath.addRect(rect, Path.Direction.CW); RectF rect1 = new RectF(-200,-100, 200, 100);//椭圆 rectPath.addOval(rect1, Path.Direction.CW); RectF rect2 = new RectF(-250,-200, 250, 200);//圆角矩形 rectPath.addRoundRect(rect2, 50, 50, Path.Direction.CCW); canvas.drawPath(rectPath, mPaint); }
在onDraw方法中调用上方法,运行效果如下:
方法中的参数含义都应该能理解到,这里重点讲解Path.Direction,Direction的意思是方向、趋势,包含两个枚举常量:
至于对闭合顺序到底有啥影响,图形的渲染等问题等请慢慢看下去。
a、先研究确定CW的闭合顺序的问题,添加一个矩形试试看:
private void addRxxCW(){ canvas.translate(wid / 2, hei / 2); Path rectPath = new Path(); RectF rect = new RectF(-200,-200, 200, 200); rectPath.addRect(rect, Path.Direction.CW); canvas.drawPath(rectPath, mPaint); }
在onDraw方法中调用上方法,运行效果如下:
b、再确定CCW的闭合顺序的问题,添加一个矩形试试看:
private void addRxxCCW(){ canvas.translate(wid / 2, hei / 2); Path rectPath = new Path(); RectF rect = new RectF(-200,-200, 200, 200); rectPath.addRect(rect, Path.Direction.CCW); canvas.drawPath(rectPath, mPaint); }
在onDraw方法中调用上方法,运行效果如下:
运行结果一模一样,感觉很神奇,并且,你他妈的都一模一样还弄两个出来搞毛啊,消遣人么?其实这个东东是自带隐身技能的,想要让它现出原形,就要用到咱们刚刚学到的setLastPoint(重置当前最后一个点的位置)。
在addRxxCCW()方法中的canvas.drawPath(rectPath, mPaint);之前再加一行代码:rectPath.setLastPoint(-250, 250);运行结果如下,可以明显看到,图形发生了奇怪的变化
需要注意的是,交换坐标点的顺序可能就会影响到某些绘制内容哦,例如上面的例子,你可以尝试交换两个坐标点,或者指定另外两个点来作为参数,虽然指定的是同一个矩形,但实际绘制出来是不同的————参数中点的顺序很重要!参数中点的顺序很重要!参数中点的顺序很重要!一定要记得,重要的事情说三遍。
第二类(Path)方法预览:
// 第二类(Path) public void addPath (Path src) public void addPath (Path src, float dx, float dy) public void addPath (Path src, Matrix matrix)
第一个方法相对比较简单,也很容易理解,就是将两个Path合并成为一个;
第二个方法比第一个方法多出来的两个参数是将src进行了位移之后再添加进当前path中;
第三个方法是将src添加到当前path之前先使用Matrix进行(矩阵)变换。难度一个个的增大。
下面我们用哪个代码来做演示:
private void addPathPaint(){ canvas.translate(wid / 2, hei / 2); canvas.scale(1, -1); Path mergePath = new Path(); Path src = new Path(); mergePath.addRect(-100,-100,100,100, Path.Direction.CW);//矩形 src.addCircle(0,100,80, Path.Direction.CW);//圆 mergePath.addPath(src);//将圆添加到矩形path可以,反过来则出问题 canvas.drawPath(mergePath, mPaint); }
在onDraw方法中调用上方法,运行效果如下:
第三类(addArc与arcTo) 方法预览:
public void addArc(RectF oval,float startAngle,float sweepAngle); public void arcTo(RectF oval,float startAngle,float sweepAngle); public void arcTo(RectF oval,float startAngle,float sweepAngle,boolean forceMoveTo);
addArc与arcTo的区别:
其中参数的含义如下:
特别注意:
sweepAngle取值范围是 [-360, 360),当 >= 360 或者 < -360 时将不会绘制任何内容, 对于360,你可以用一个接近的值替代,例如: 359.99。
forceMoveTo作用: 是否使用moveTo强制将变量移动到圆弧的起点位移。
addArc ()示例:
private void drawAddArc(Canvas canvas, Paint mPaint){ canvas.translate(wid / 2, hei / 2);// 移动坐标系到屏幕中心 Path path = new Path(); path.lineTo(141.5f, 141.5f);//画直线 RectF oval = new RectF(-200, -200, 200, 200);//画圆弧 //path.addArc(oval, 135, 270); path.arcTo(oval, 135, 270, true);//和上面一句作用等价 canvas.drawPath(path, mPaint); }
在onDraw方法中调用上方法,运行效果如下:
arcTo ()示例:
private void drawArcTo(Canvas canvas, Paint mPaint){ canvas.translate(wid / 2, hei / 2); // 移动坐标系到屏幕中心 Path path = new Path(); path.lineTo(141.5f, 141.5f); RectF oval = new RectF(-200, -200, 200, 200); //path.addArc(oval, 135, 270); //arcTo中Boolean值作用:是否形成封闭的图形 path.arcTo(oval, 135, 270, false);//和上一行代码作用等价 canvas.drawPath(path,mPaint); }
在onDraw方法中调用上方法,运行效果如下:
第3组:isEmpty、 isRect、isConvex、 set 、offset:
这一组比较简单,稍微说一下就可以了。
isEmpty()方法预览:
public boolean isEmpty ();作用是判断path中是否包含内容。 Path path = new Path(); Log.e("1",path.isEmpty()+""); path.lineTo(100,100); Log.e("2",path.isEmpty()+"");
log输出结果: com.sloop.canvas E/1: true;;com.sloop.canvas E/2: false
isRect()方法预览:
public boolean isRect (RectF rect); 作用是判断path是否是一个矩形,如果是,会将矩形的信息存放进参数rect中 path.lineTo(0,400); path.lineTo(400,0); path.lineTo(0,0); RectF rect = new RectF(); boolean b = path.isRect(rect); Log.e("Rect","isRect:"+b+"| left:"+rect.left+"| top:"+rect.top+"| right:"+rect.right+"| bottom:"+rect.bottom);
log 输出结果:
com.sloop.canvas E/Rect: isRect:true| left:0.0| top:0.0| right:400.0| bottom:400.0
set()方法预览:
public void set (Path src); 将新的path赋值到现有path。 canvas.translate(mWidth / 2, mHeight / 2); // 移动坐标系到屏幕中心 canvas.scale(1,-1);// <-- 注意 翻转y坐标轴 Path path = new Path();// path添加一个矩形 path.addRect(-200,-200,200,200, Path.Direction.CW); Path src = new Path();// src添加一个圆 src.addCircle(0,0,100, Path.Direction.CW); path.set(src);// 大致相当于 path = src; canvas.drawPath(path,mPaint);
运行结果如下:
offset()方法预览:
public void offset (float dx, float dy); public void offset (float dx, float dy, Path dst);
这个的作用就是对path进行一段平移,它和Canvas中的translate作用很像,但Canvas作用于整个画布,而path的offset只作用于当前path。第二个方法的dst参数是存储平移后的path的: dst不为空, 将当前path平移后的状态存入dst中,不会影响当前path; dst为空(null),平移将作用于当前path,相当于第一种方法。
canvas.translate(mWidth / 2, mHeight / 2);// 移动坐标系到屏幕中心 canvas.scale(1,-1);// <-- 注意 翻转y坐标轴 Path path = new Path();// path中添加一个圆形(圆心在坐标原点) path.addCircle(0,0,100, Path.Direction.CW); Path dst = new Path();// dst中添加一个矩形 dst.addRect(-200,-200,200,200, Path.Direction.CW); path.offset(300,0,dst);// 平移 canvas.drawPath(path,mPaint);// 绘制path mPaint.setColor(Color.BLUE);// 更改画笔颜色 canvas.drawPath(dst,mPaint);// 绘制dst
运行结果如下:
第4组: rXxx方法,该方法整体上来讲就是利用相对坐标编程。
rXxx方法的坐标使用的是相对位置(基于当前点的位移),而之前方法的坐标是绝对位置(基于当前坐标系的坐标)。最前面的r就是RelativeLayout的缩写。
使用如下:
private void drawRxxx(Canvas canvas, Paint mPaint){ Path path = new Path(); path.lineTo(100, 200); canvas.drawPath(path, mPaint); Path path1 = new Path(); path1.moveTo(100, 100); //Rxxx系列方法:相对坐标编程 //相对于上一个点(100, 100);绝对坐标下的坐标为:(200, 300) path1.rLineTo(100, 200); canvas.drawPath(path1, mPaint); canvas.drawCircle(200, 300, 10, mPaint); }
onDraw方法里面利用上述方法啊,运行结果如下:
此处仅以 rLineTo 为例,只要理解 “绝对坐标” 和 “相对坐标” 的区别,其他方法类比即可。
布尔操作(API19):
布尔操作与我们中学所学的集合操作非常像,只要知道集合操作中的子集,交集,并集,差集,补集等操作,那么理解布尔操作也是很容易的。
布尔操作是两个Path之间的运算,主要作用是用一些简单的图形通过一些规则合成一些相对比较复杂,或难以直接得到的图形。
布尔运算的核心:布尔逻辑,它有五种逻辑,如下:
在Path中的布尔运算有两个方法:
boolean op (Path path, Path.Op op); boolean op (Path path1, Path path2, Path.Op op);
两个方法中的返回值用于判断布尔运算是否成功,它们使用方法如下:
对 path1 和 path2 执行布尔运算,运算方式由第二个参数指定,运算结果存入到path1中。
path1.op(path2, Path.Op.DIFFERENCE); // 对 path1 和 path2 执行布尔运算,运算方式由第三个参数指定,运算结果存入到path3中。 path3.op(path1, path2, Path.Op.DIFFERENCE);
如太极中的阴阳鱼,如果用贝塞尔曲线制作的话,可能需要六段贝塞尔曲线才行,而在这里我们可以用四个Path通过布尔运算得到,而且会相对来说更容易理解一点。
这里我就用画阴阳鱼来演示布尔操作:
private void drawTaiJi(Canvas canvas, Paint mPaint){ canvas.translate(wid / 2, hei / 2); mPaint.setStrokeWidth(5); mPaint.setColor(Color.BLACK); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); Path path1 = new Path(); Path path2 = new Path(); Path path3 = new Path(); Path path4 = new Path(); path1.addCircle(0, 0, 200, Path.Direction.CW); path2.addRect(0, -200, 200, 200, Path.Direction.CW); path3.addCircle(0, -100, 100, Path.Direction.CW); path4.addCircle(0, 100, 100, Path.Direction.CCW); path1.op(path2, Path.Op.DIFFERENCE); path1.op(path3, Path.Op.UNION); path1.op(path4, Path.Op.DIFFERENCE); canvas.drawPath(path1, mPaint); mPaint.setStyle(Paint.Style.STROKE); canvas.drawCircle(0, 0, 200, mPaint); mPaint.setStyle(Paint.Style.FILL); canvas.drawCircle(0, 100, 30, mPaint); mPaint.setColor(Color.WHITE); canvas.drawCircle(0, -100, 30, mPaint); }
onDraw方法里面利用上述方法啊,运行结果如下:
Path的基本操作到此结束。
相关文章推荐
- 自定义View学习笔记09—Path之Bezier
- 安卓自定义View进阶-Path之基本操作
- Android自定义View(八)_Path之基本操作
- 安卓自定义View进阶:Path基本操作
- 安卓自定义View进阶:Path基本操作
- 自定义view——Path之基本操作(转载)-8
- iOS学习笔记---数据库SQLite3的基本操作并讲内容显示在tableView中
- iOS学习笔记-059.自定义View05——自定义基本的UIImageView
- WPF and Silverlight 学习笔记(二十七):基本图形的使用(2)Path和位图操作
- 自定义VIEW(学习笔记三)-基本图形的绘制
- WPF and Silverlight 学习笔记(二十七):基本图形的使用(2)Path和位图操作
- 安卓自定义View进阶-Path之基本操作
- 自定义View学习笔记05—Canvas下操作画布
- 学习笔记---线性表的基本操作---顺序存储(C语言)
- Emacs 学习笔记1 基本操作(和Vim 命令对照)
- PHP学习笔记(2)--PHP数据库操作基本知识
- iPhone开发学习笔记005——使用XIB自定义一个UIView,然后将这个view添加到controller的view
- iphone学习笔记--UITableView的基本方法
- JAVA学习笔记(2)基本数据类型和基本操作