今天周一,产品要求版本迭代到1.5.3,发现需求没啥东西,后台暂时也给不了数据,于是又有时间写博客了,这是我很喜欢的模式,今天讲下path的基本使用以及贝塞尔曲线入门,后期会讲些贝塞尔曲线结合动画的效果,瞬间让你装逼找不到自己,当然这中间需要时间去研究,这是一个快乐的过程,毕竟这是一个自己感兴趣的事,年龄大了,发现能干自己感兴趣的事还能赚钱养活自己都不容易,切入正题
Path是一个神奇的东西,能把它搞懂,可以实现网上看到的很多效果,现在开始讲下Path的基本使用
我们知道在canvas中有个方法canvas.drawPath(path,paint);这就是绘制path,path就是一条路径可以简单的理解为,google官方SDK解释:
/** * The Path class encapsulates compound (multiple contour) geometric paths * consisting of straight line segments, quadratic curves, and cubic curves. * It can be drawn with canvas.drawPath(path, paint), either filled or stroked * (based on the paint's Style), or it can be used for clipping or to draw * text on a path. */看不懂怎么办,没关系,我也看不懂,但是不影响你实现你想实现的效果,如果你那天成功了,谁还在意你的过去,只要你不和方舟子合不来一般是没问题的,我们学这些无非是看它的api提供了什么方法,然后每个方法有啥用,应用层就是这么玩的,
path方法如下:
path构造函数就2个,一个是无参的,一个是带参的
public Path(Path src) 这是通过传递一个path构建一个新的path路径,现在讲讲常用的方法
1:reset() 意思是重置,其实是把你绘制在path上的图形全部清除,比如你在这path绘制了线或者点什么的,调用了reset()方法后,path上什么都没了
2:set(Path path)用传递过来的path代替之前path上的绘制的内容,这个进入源码有注释的,
3:moveTo(float startX,float endY);绘制线的起点坐标,如果不指定的话,系统默认是在原点(0,0)开始,这个写个demo就能测试出来
4:lineTo(float x,float y)这是配合moveTo()使用的,表示二个点连接成一条线,lineTo(x,y)在有moveTo()时候相当于终点,在多次调用的时候相当于起点,写个demo,说明下
package smart.com.pathview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.View; /** * Created by admin on 2016/12/7. */ public class PathDemo extends View { private Paint paint; private Path path; public PathDemo(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(); paint.setColor(Color.DKGRAY); paint.setStrokeWidth(2); paint.setStyle(Paint.Style.STROKE); path = new Path(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawPath(path,paint); path.moveTo(10,10);//起点 path.lineTo(100,100);//终点 path.lineTo(200,200);//这个起点是相当于 100,100 canvas.drawPath(path,paint); } }效果:
5:rMoveTo(),rLineTo(),path类还有其他方法带r的都是相对于某一个点,rLineTo()是相当于rMoveTo()点坐标的,比如rMoveTo(10,10) 而rLine(100,100)相当于rMoveTo()起点而言,最终的绘制一条线的起点为(10,10),终点为(100+10,100+10),这个很好测试,其实你绘制线后再绘制二个终点的坐标,一看就知道了
package smart.com.pathview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.View; /** * Created by admin on 2016/12/7. */ public class PathDemo extends View { private Paint paint; private Path path,path1; public PathDemo(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(); paint.setColor(Color.RED); paint.setStrokeWidth(2); paint.setStyle(Paint.Style.STROKE); paint.setAntiAlias(true); path = new Path(); path1 = new Path(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); path.moveTo(10,10); path.lineTo(200,200); canvas.drawPath(path,paint); paint.setColor(Color.BLUE); path1.rMoveTo(100,10); path1.rLineTo(300,10); canvas.drawPath(path1,paint); paint.setColor(Color.BLACK); paint.setStrokeWidth(8); //绘制2个点测试 canvas.drawPoint(200,200,paint); canvas.drawPoint(400,20,paint); } }效果:
看图说话,
6:add...(),path中很多add()方法我截图看下:
什么添加椭圆 添加弧度,矩形,圆角矩形,圆形等,现在就写个添加圆形玩玩
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); path.addCircle(200,200,150, Path.Direction.CCW); canvas.drawPath(path,paint); }效果图:
你会发现path.addCircle()有一个参数Path.Direction.CCW,啥意,点击进去看源码,发现一个单词clockwise,意思是顺时针方向,那么Path.Direction.CW就是反方向了,这个你画圆时看不出来的,画什么矩形也是看不出来的,那么canvas还有一个方法,用这个方法来测试上面的2个参数什么顺时针和逆时针一眼就看的出来
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); RectF rectF = new RectF(60,60,400,400); path.addRect(rectF, Path.Direction.CCW); canvas.drawPath(path,paint); paint.setColor(Color.MAGENTA); paint.setTextSize(24); paint.setStrokeWidth(2); canvas.drawTextOnPath("杭州今天天气不错",path,0,0,paint); }效果:
Direction.CW 逆时针:
ok,这样直观一眼就看的出来,
7:close()闭合,就是当path绘制线大于或者等于3条的时候,使用close会构成一个封闭的图形,比如绘制三角形或者矩形
8:isEmpty()是否是空
9:isRect()是否是矩形
10:setFillType(FillType ft)填充模式:进入源码发现有如下几种:
public enum FillType { // these must match the values in SkPath.h /** * Specifies that "inside" is computed by a non-zero sum of signed * edge crossings. */ WINDING (0), /** * Specifies that "inside" is computed by an odd number of edge * crossings. */ EVEN_ODD (1), /** * Same as { @link #WINDING}, but draws outside of the path, rather than inside. */ INVERSE_WINDING (2), /** * Same as { @link #EVEN_ODD}, but draws outside of the path, rather than inside. */ INVERSE_EVEN_ODD(3); FillType(int ni) { nativeInt = ni; } final int nativeInt; }发现有四种填充模式:前提是path添加的图形要相交
WINDING:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mEndPath = new Path(); mEndPath.offset(100,100); mEndPath.addCircle(200, 200, 100, Path.Direction.CW); mEndPath.addCircle(300, 300, 100, Path.Direction.CW); mEndPath.setFillType(Path.FillType.WINDING); paint.setColor(Color.RED); canvas.drawPath(mEndPath,paint); }效果:
EVEN_ODD:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mEndPath = new Path(); mEndPath.offset(100,100); mEndPath.addCircle(200, 200, 100, Path.Direction.CW); mEndPath.addCircle(300, 300, 100, Path.Direction.CW); mEndPath.setFillType(Path.FillType.EVEN_ODD); paint.setColor(Color.RED); canvas.drawPath(mEndPath,paint); }效果: