Android 绘图学习
1 PathEffect 概念
Paint的setPathEffect函数用于设置绘制几何时的路径样式(线条的轮廓),PathEffect从名字就可以知道主要作用于Path路径,PathEffect是个基类,要实现具体功能需要利用具体的实现类。
PathEffect的实现类包括ComposePathEffect,CornerPathEffect,DashPathEffect,DiscretePathEffect,PathDashPathEffect,SumPathEffect。
各个实现类的作用:
ComposePathEffect和SumPathEffect用于组合两种路径效果,
CornerPathEffect设置路径连线之间的夹角更加平滑,圆润,
DashPathEffect,PathDashPathEffect虚线效果,动态改变会产生动画效果,
DiscretePathEffect会产生一种离散效果,具体就是会在路径上绘制许多杂点。
2 CornerPathEffect:
/**
- Transforms geometries that are drawn (either STROKE or FILL styles) by
- replacing any sharp angles between line segments into rounded angles of
- the specified radius.
- @param radius Amount to round sharp angles between line segments.
*/
将Path的各个连接线段之间的夹角用一种更平滑的方式连接,一般的,通过CornerPathEffect(float radius)指定一个具体的圆弧半径来实例化一个CornerPathEffect。利用指定半径圆的角替换多个线段之间的连接点,参数radius就是线段之间的圆角的圆滑程度(连接两条直线所使用的圆的半径)。
示例代码:
mPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint1.setColor(Color.BLUE);
mPaint1.setStrokeWidth(10);
mPaint1.setStyle(Paint.Style.STROKE);
mPath1 = new Path();
mPath1.moveTo(150,250);
mPath1.lineTo(250,320);
mPath1.lineTo(300,300);
mPath1.lineTo(350,350);
mPath1.lineTo(420,270);
mPath1.lineTo(540,370);
mPath1.lineTo(560,300);
mPath1.lineTo(650,340);
mPath1.lineTo(750,270);
mPath1.lineTo(850,330);
mPath1.lineTo(950,240);
mPath1.lineTo(1050,290);
mPath1.lineTo(1150,350);
mPath1.lineTo(1250,230);
mPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint2.setColor(Color.BLUE);
mPaint2.setStrokeWidth(10);
mPaint2.setStyle(Paint.Style.STROKE);
mPaint2.setPathEffect(new CornerPathEffect(30));
mPath2 = new Path();
mPath2.moveTo(150,550);
mPath2.lineTo(250,620);
mPath2.lineTo(300,600);
mPath2.lineTo(350,650);
mPath2.lineTo(420,570);
mPath2.lineTo(540,670);
mPath2.lineTo(560,600);
mPath2.lineTo(650,640);
mPath2.lineTo(750,570);
mPath2.lineTo(850,630);
mPath2.lineTo(950,540);
mPath2.lineTo(1050,590);
mPath2.lineTo(1150,650);
mPath2.lineTo(1250,530);
canvas.drawPath(mPath1,mPaint1);
canvas.drawPath(mPath2,mPaint2);
canvas.drawRect(200,800,700,1100,mPaint2);
mPaint2.setTextSize(130);
mPaint2.setStrokeWidth(5);
mPaint1.setTextSize(130);
mPaint1.setStrokeWidth(5);
canvas.drawText("欢迎,你好啊!",200,1400,mPaint1);
canvas.drawText("欢迎,你好啊!",200,1700,mPaint2);
从图中可以明显看到设置了CornerPathEffect的路径更加的平滑,对绘制的矩形也有平滑作用,效果类似绘制圆角矩形,对文字没有效果。
Paint的Style设置为Stroke和FILL_AND_STROKE时对线段和矩形都有圆滑作用,设置为FILL(没有描边)时只对直线有作用,对矩形没有作用。
设置为FILL_AND_STROKE
设置为FILL:
3 DashPathEffect,PathDashPathEffect
/**
* The intervals array must contain an even number of entries (>=2), with
* the even indices specifying the "on" intervals, and the odd indices
* specifying the "off" intervals. phase is an offset into the intervals
* array (mod the sum of all of the intervals). The intervals array
* controls the length of the dashes. The paint's strokeWidth controls the
* thickness of the dashes.
* Note: this patheffect only affects drawing with the paint's style is set
* to STROKE or FILL_AND_STROKE. It is ignored if the drawing is done with
* style == FILL.
* @param intervals array of ON and OFF distances
* @param phase offset into the intervals array
*/
DashPathEffect将Path的线段虚线化,构造函数为DashPathEffect(float[] intervals, float offset),intervals:是间隔数组,作为实线,虚线的开关,设置虚线实线的长度,该数组的length必须大于等于2,如果设置两个参数就按两个参数循环,第一个参数为“实线长度”,第二个参数为“虚线长度”后面依次循环,还可以设置多个参数(如果是奇数个参数,最后一个参数无效,具体没仔细验证,如果用到大家仔细求证下)。这个PathEffect只对设置Stroke 或者FILL_AND_STROKE 样式的Paint有效,Style为FILL时则失效。
phase为绘制时的偏移量,改变这个值可以实现类似虚实交换的动画效果,phase改变的越大,则动画效果越明显。
代码示例:
float[] array1 = {50,20};
mPaint2.setPathEffect(new DashPathEffect(array1, 5));
动态修改phase:
PathDashPathEffect
PathDashPathEffect功能类似DashPathEffect,但是它是利用特定的Path形状绘制路径,只有Paint的style是 STROKE or STROKE_AND_FILL时起作用,strokeWidth不影响结果。
构造函数
PathDashPathEffect(Path shape, float advance, float phase,Style style)
参数说明:
shape:路径上的形状,Path内部添加路径形状,类似矩形,三角形等,
advance :两个形状间的距离,如果具体够大可以放好多形状,如果距离过小,只能放置一个形状
phase:偏移距离,和DashPathEffect一样,可以实现动画效果。
style是每个形状的排列方式)(特别是在转角处),共有三种样式,
TRANSLATE(0), //平移每个位置的形状,就是改变印章的位置。
ROTATE(1), //绕着每个形状的中心旋转
MORPH(2); //每个点变换形状, 并把直线变成曲线(在转角处)
ROTATE的情况下,线段连接处的图形转换以旋转到与下一段移动方向相一致的角度进行转转,MORPH时图形会以发生拉伸或压缩等变形的情况与下一段相连接,TRANSLATE时,图形会以位置平移的方式与下一段相连接。
shape是有宽高的,不同的style形状的绘制方式不同,所以如果advance间距过小,所有的形状都会绘制在一起,就无法看出具体的形状了,所以设置advance时要尽量大一点。
Path tPath = new Path();
tPath.addRect(0f,0f,20f,30f, Path.Direction.CW);
mPaint1.setPathEffect(new PathDashPathEffect(tPath,50,50,PathDashPathEffect.Style.ROTATE));
mPaint2.setPathEffect(new PathDashPathEffect(tPath,50,50,PathDashPathEffect.Style.TRANSLATE));
mPaint3.setPathEffect(new PathDashPathEffect(tPath,50,50,PathDashPathEffect.Style.MORPH));
在路径上绘制矩形,分别设置不同style:
如果设置advance设置过小:
Path tPath = new Path();
tPath.addRect(0f,0f,20f,30f, Path.Direction.CW);
mPaint2.setPathEffect(new PathDashPathEffect(tPath,20,50,PathDashPathEffect.Style.TRANSLATE));
mPaint1.setPathEffect(new PathDashPathEffect(tPath,20,50,PathDashPathEffect.Style.ROTATE));
mPaint3.setPathEffect(new PathDashPathEffect(tPath,20,50,PathDashPathEffect.Style.MORPH));
设置advance过小,虽然看着不好看,但是可以看出style的效果,MORPH通过变形使线段更平滑,TRANSLATE靠平移,所有的形状都不会变形且形状整体在一条线上,ROTATE利用旋转,跟平移有点相似,但是只有旋转中心在一条线上。
5 DiscretePathEffect
这个类的作用术语称为离散路径,使得在原来路径的基础上发生打散效果。
构造函数:
DiscretePathEffect(float segmentLength,float deviation)
segmentLength指定切割的段长,
deviation指定可偏移的距离(离原来的点),越大可偏移的距离越大。
将路径分隔成定长的线段,然后将每条线段随机偏移一段位置,就会产生打散的效果。
mPaint1.setPathEffect(new DiscretePathEffect(10,10));
mPaint2.setPathEffect(new DiscretePathEffect(10,30));
mPaint3.setPathEffect(new DiscretePathEffect(20,10));
segmentLength越长,线段被切割的分成的段越少,离散的点也就越少,
deviation 越大,线段偏移的越厉害,看着也不规则(毛刺比较多),
上面的实例代码mPaint1和mPaint2 segmentLength相同,deviation不同,
mPaint1和mPaint3 deviation相同,segmentLength不同。
6 ComposePathEffect与SumPathEffect
都是用来组合两个PathEffect的但效果不同。
ComposePathEffect需要两个PathEffect参数来构造一个实例,
/**
* Construct a PathEffect whose effect is to apply first the inner effect
* and the the outer pathEffect (e.g. outer(inner(path))).
*/
ComposePathEffect(PathEffect outerpe, PathEffect innerpe)
作用是先将outerpe的效果作用到路径上,然后再在变换后的路径上添加innerpe效果
SumPathEffect:
/**
* Construct a PathEffect whose effect is to apply two effects, in sequence.
* (e.g. first(path) + second(path))
*/
public SumPathEffect(PathEffect first, PathEffect second) ;
需要两个PathEffect作为参数,但与ComposePathEffect不同的是,作用是会分别对两个参数的效果各自独立进行表现,然后将两个效果简单的重叠在一起显示出来。
CornerPathEffect cornerPathEffect = new CornerPathEffect(30);
float[] array1 = {50,20};
DashPathEffect dashPathEffect = new DashPathEffect(array1, phase);
ComposePathEffect composePathEffect = new ComposePathEffect(dashPathEffect, cornerPathEffect);
SumPathEffect sumPathEffect = new SumPathEffect(dashPathEffect, cornerPathEffect);
mPaint1.setPathEffect(composePathEffect);
mPaint2.setPathEffect(sumPathEffect);
mPaint1先圆角,在虚线化。
mPaint2 圆角和虚线叠加效果。
android绘图之Paint(1)
android绘图之Canvas基础(2)
Android绘图之Path(3)
Android绘图之drawText绘制文本相关(4)
Android绘图之Canvas概念理解(5)
Android绘图之Canvas变换(6)
Android绘图之Canvas状态保存和恢复(7)
Android绘图之PathEffect (8)
Android绘图之LinearGradient线性渐变(9)
Android绘图之SweepGradient(10)
Android绘图之RadialGradient 放射渐变(11)
Android绘制之BitmapShader(12)
Android绘图之ComposeShader,PorterDuff.mode及Xfermode(13)
Android绘图之drawText,getTextBounds,measureText,FontMetrics,基线(14)
Android绘图之贝塞尔曲线简介(15)
Android绘图之PathMeasure(16)
Android 动态修改渐变 GradientDrawable