自定义View之Paint - PathEffect

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/IO_Field/article/details/78630299

setPathEffect(PathEffect effect)

setPathEffect方法为指定的Path设置展现的样式,PathEffect这个类并没有具体的实现,其效果要看它的六个子类:

这里写图片描述

效果图如下:

这里写图片描述

CornerPathEffect

构造函数:

CornerPathEffect(float radius)

这个类的作用就是将Path的各个连接线段之间的夹角用指定半径的圆,以一种更平滑的方式连接,类似于圆弧与切线的效果(STROKE或FILL样式)。

示例代码:

val cornerPathEffect = CornerPathEffect(24f)
mPaint.pathEffect = cornerPathEffect
canvas?.drawPath(path, mPaint)

现指定两个线段之间的夹角的的圆弧的半径为24f, 折线的两个线的连接点不再是锐角还是一个弧度:

这里写图片描述

DashPathEffect

构造函数:

DashPathEffect(float[] intervals, float phase)

这个类的作用是将Path路径上的线段虚线化。如果想绘制虚线,可以使用此类。其中:

扫描二维码关注公众号,回复: 2942434 查看本文章
  • intervals:间隔数组必须包含偶数个条目(> = 2),偶数索引指定“on”间隔即实线,而奇数索引指定“off”间隔即空白。
  • phase的作用是偏移指定的长度的开始画,但是总长度是不变的。

对于phase,这个偏移量是怎么理解的呢?在intervals数组中,该虚线的效果实现,intervals中所有元素的和为一组虚线的长度,而整个绘制是由N组这些虚线来组成。默认的又是从起始索引开始画,即为实线。当指定phase之后,它会将虚线偏移指定长度后,从哪里开始绘画,而不是起始索引。

现绘制两条虚线,将实线和空白都设置为40px,为了便于观察偏移量的效果,将第一条虚线没有偏移量,第二条虚线的偏移量为100f:

val dashPathEffect = DashPathEffect(floatArrayOf(40f, 40f), 0f)
mPaint.pathEffect = dashPathEffect
canvas?.drawPath(path, mPaint)

path.offset(0f, 120f)
val dashPathEffectPhase = DashPathEffect(floatArrayOf(40f, 40f), 100f)
mPaint.pathEffect = dashPathEffectPhase
canvas?.drawPath(path, mPaint)

从下图中可以清楚地看到,第二条虚线与第一条虚线的效果不一样,由于第二条虚线的偏移量为100f,经过计算,第二条虚线的绘制应该是从起始实线的20f处开始绘制。

这里写图片描述

如果动态的改变phase值,又会然路径的绘制产生动画的效果。

override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)

    val dashPathEffect = DashPathEffect(floatArrayOf(40f, 40f), 0f)
    mPaint.pathEffect = dashPathEffect
    canvas?.drawPath(path, mPaint)

    path.offset(0f, 120f)
    val dashPathEffectPhase = DashPathEffect(floatArrayOf(40f, 40f), mPhase)
    mPaint.pathEffect = dashPathEffectPhase
    canvas?.drawPath(path, mPaint)


    mPhase++

    if (mPhase == 40f) {
        mPhase = 0f
    }

    invalidate()
}

DiscretePathEffect

构造函数:

DiscretePathEffect(float segmentLength, float deviation)

这个类的作用是打散Path的线段,使得在原来路径的基础上发生打散效果。

其中:

  • segmentLength:指定最大的段长
  • deviation:指定偏离量

现创建一个DiscretePathEffect,其打散线段的最大长度为96px,而偏离量为16f:

val discretePathEffect = DiscretePathEffect(96f, 16f)
mPaint.pathEffect = discretePathEffect
canvas?.drawPath(path, mPaint)

在绘制时,不会再根据路径来绘制线段,而是打散原来的线段的坐标分布,同时将其在指定的范围内偏移,有可能造成折点比原来线段的折点多,或者比原来的线段折点少,实际效果是随机的。

这里写图片描述

SumPathEffect

构造函数:

SumPathEffect(PathEffect first, PathEffect second)

这个类将实现两个PathEffect的叠加效果,它接受两个指定的PathEffect,它会分别对PathEffect的效果各自独立进行表现,然后将两个效果简单的重叠在一起显示出来。

现创建一个CornerPathEffect实例,然后创建了一个DashPathEffect实例,其间隔数组为[10f, 10f],并将它们其传递给SumPathEffect实例:

val cornerPathEffect = CornerPathEffect(64f)
val dashPathEffect = DashPathEffect(floatArrayOf(40f, 40f), 0f)
val sumPathEffect = SumPathEffect(cornerPathEffect, dashPathEffect)
mPaint.pathEffect = sumPathEffect
canvas?.drawPath(path, mPaint)

实际上,两个虚线的效果都展现出来了,更像是两个PathEffect在一起显示,不过它们都是相对独立存在的。

这里写图片描述

ComposePathEffect

构造函数:

ComposePathEffect(PathEffect outerpe, PathEffect innerpe)

这个类与SumPathEffect类似,也是将实现PathEffect的组合效果,不同的是,其先绘制innerpe然后再绘制outerpe,它首先将innerpe表现出来,然后再在innerpe的基础上去增加outerpe的效果。

使用SumPathEffect示例所用的两个DashPathEffect传递给ComposePathEffect:

val dashPathEffectPhase = DashPathEffect(floatArrayOf(30f, 30f), 0f)
val dashPathEffect = DashPathEffect(floatArrayOf(40f, 40f), 0f)
val composePathEffect = ComposePathEffect(dashPathEffectPhase, dashPathEffect)
mPaint.pathEffect = composePathEffect
canvas?.drawPath(path, mPaint)

它的效果明显与SumPathEffect不一样,它首先是一条虚线,而在其相交处做了圆滑的处理,更像是两个PathEffect产生了化学反应,其效果是它们两个的混合效果,而不是单独存在的。

这里写图片描述

PathDashPathEffect

它与DashPathEffect类类似,也是绘制一种虚线,不同的是:

  1. 它的实线不再是线,而是指定的Path图形
  2. 空白的距离是指定的,不再像DashPathEffect那样,接受一个间隔数组

构造函数:

PathDashPathEffect(Path shape, float advance, float phase, PathDashPathEffect.Style style)

各个参数的含义:

  • shape:填充图形的路径
  • advance:每个图形间的间距
  • phase:偏移量
  • style为枚举PathDashPathEffect.Style的值

    • Style.ROTATE:线段连接处的图形转换以旋转到与下一段移动方向相一致的角度进行转转
    • Style.MORPH:图形会以发生拉伸或压缩等变形的情况与下一段相连接
    • Style.TRANSLATE:图形会以位置平移的方式与下一段相连接。

使用PathDashPathEffect之前,首先指定一个Path路径来绘制实线的图形,比如下图绘制了一个三角形:

val shape = Path()
shape.lineTo(0f, 30f)
shape.lineTo(30f, 30f)
shape.lineTo(0f, 0f)

现创建一个PathDashPathEffect实例,并将刚才创建的Path传递给它:

val pathDashPathEffect = PathDashPathEffect(shape, 45f, 0f, PathDashPathEffect.Style.ROTATE)
mPaint.pathEffect = pathDashPathEffect
canvas?.drawPath(path, mPaint)

path.offset(0f, 160f)
val pathDashPathEffect1 = PathDashPathEffect(shape, 45f, 0f, PathDashPathEffect.Style.MORPH)
mPaint.pathEffect = pathDashPathEffect1
canvas?.drawPath(path, mPaint)


path.offset(0f, 160f)
val pathDashPathEffect2 = PathDashPathEffect(shape, 45f, 0f, PathDashPathEffect.Style.TRANSLATE)
mPaint.pathEffect = pathDashPathEffect2
canvas?.drawPath(path, mPaint)

效果图:

这里写图片描述


如果觉得我的文章对您有用,请随意点赞、评论。您的支持将鼓励我继续创作!

猜你喜欢

转载自blog.csdn.net/IO_Field/article/details/78630299