欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Jetpack Compose Drawing Canvas、DrawScope 和 Modifier.drawWithContent、BlendMode 解释

最编程 2024-05-09 09:12:12
...

这篇文章我们会介绍Compose中如何去自定义绘制一些图形,会介绍Canvas,DrawScope,以及Modifier.drawWithContent的用法。

一 :Canvas,DrawScope

先来看看代码:

@Composable
fun Canvas(modifier: Modifier, onDraw: DrawScope.() -> Unit) =
    Spacer(modifier.drawBehind(onDraw))
  • modifier 修饰符以前的文章讲过Modifier用法详解
  • onDraw 其实就是DrawScope。DrawScope点进去查看代码,主要有如下几个方法
    • drawLine 画线
    • drawRect 画矩形
    • drawRoundRect 画圆角矩形
    • drawImage 绘制图片
    • drawCircle 画圆形
    • drawOval 画椭圆形
    • drawArc 画弧度跟扇形
    • drawPath 画路径
    • drawPoints 画点 还有如下几个扩展方法
    • inset 将DrawScope坐标空间平移
    • translate 平移坐标
    • rotate(旋转坐标)讲的是旋转了多少角度,rotateRad(旋转坐标)讲的是旋转了多少弧度
    • scale 缩放坐标
    • clipRect 裁剪矩形区域,绘制在裁剪好的矩形区域内。ClipOp.Difference从当前剪辑中减去提供的矩形。
    • clipPath 裁剪路径
    • drawIntoCanvas 直接提供底层画布
    • withTransform 组合转换 我们看到会有很多的绘制的方法,一个个来看,一个个来试

1.1 DrawScope的drawLine 方法

fun drawLine(
        brush: Brush,
        start: Offset,
        end: Offset,
        strokeWidth: Float = Stroke.HairlineWidth,
        cap: StrokeCap = Stroke.DefaultCap,
        pathEffect: PathEffect? = null,
        /*FloatRange(from = 0.0, to = 1.0)*/
        alpha: Float = 1.0f,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)

fun drawLine(
        color: Color,
        start: Offset,
        end: Offset,
        strokeWidth: Float = Stroke.HairlineWidth,
        cap: StrokeCap = Stroke.DefaultCap,
        pathEffect: PathEffect? = null,
        /*FloatRange(from = 0.0, to = 1.0)*/
        alpha: Float = 1.0f,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)
  • brush 是刷子,就填充线的颜色的刷子,主要是处理渐变的。有几种实现如下:\
    1. 线性的渐变
    @Stable
    fun linearGradient(
        vararg colorStops: Pair<Float, Color>,
        start: Offset = Offset.Zero,
        end: Offset = Offset.Infinite,
        tileMode: TileMode = TileMode.Clamp
    ){...}
    
    @Stable
    fun linearGradient(
        colors: List<Color>,
        start: Offset = Offset.Zero,
        end: Offset = Offset.Infinite,
        tileMode: TileMode = TileMode.Clamp
    ){...}
    
    • colorStops跟colors 都是渐变颜色

    • start 开始的位置

    • end 结束的位置

    • tileMode 有三种 TileMode.Clamp(默认就是这种,最接近该区域的点的颜色),TileMode.Repeated(边从第一种颜色重复到最后一种颜色),TileMode.Mirror (边从最后一种颜色镜像到第一种颜色)

    1. 水平方向的渐变
    @Stable
    fun horizontalGradient(
       colors: List<Color>,
       startX: Float = 0.0f,
       endX: Float = Float.POSITIVE_INFINITY,
       tileMode: TileMode = TileMode.Clamp
    ){...}
    
    @Stable
    fun horizontalGradient(
      vararg colorStops: Pair<Float, Color>,
      startX: Float = 0.0f,
      endX: Float = Float.POSITIVE_INFINITY,
      tileMode: TileMode = TileMode.Clamp
    ){...}
    
    • colors,colorStops都是渐变的颜色

    • startX 开始的x轴坐标

    • endX 结束的x轴坐标

    • tileMode 跟上面一样

    1. 竖直方向的渐变
    @Stable
    fun verticalGradient(
       colors: List<Color>,
       startY: Float = 0.0f,
       endY: Float = Float.POSITIVE_INFINITY,
       tileMode: TileMode = TileMode.Clamp
    )
    
    @Stable
    fun verticalGradient(
        vararg colorStops: Pair<Float, Color>,
        startY: Float = 0f,
        endY: Float = Float.POSITIVE_INFINITY,
        tileMode: TileMode = TileMode.Clamp
    )
    
    • colors,colorStops都是渐变的颜色
    • startY 开始的y坐标
    • endY 结束的y坐标
    • tileMode 跟上面一致 4.径向的渐变
    @Stable
    fun radialGradient(
        vararg colorStops: Pair<Float, Color>,
        center: Offset = Offset.Unspecified,
        radius: Float = Float.POSITIVE_INFINITY,
        tileMode: TileMode = TileMode.Clamp
    ){...}
    
    @Stable
    fun radialGradient(
        colors: List<Color>,
        center: Offset = Offset.Unspecified,
        radius: Float = Float.POSITIVE_INFINITY,
        tileMode: TileMode = TileMode.Clamp
    ){...}
    
    • colorStops,colors 都是渐变的颜色
    • center 圆形的坐标
    • radius 半径
    • tileMode 跟上面一致
    1. 扫描的渐变
    @Stable
    fun sweepGradient(
       vararg colorStops: Pair<Float, Color>,
       center: Offset = Offset.Unspecified
    )
    
    @Stable
    fun sweepGradient(
       colors: List<Color>,
       center: Offset = Offset.Unspecified
    )
    
    • colorStops 跟colors 都是渐变的颜色
    • center 扫描的中心点
  • color 是线的颜色
  • start 是线的起始点位置
  • end 是线的终点位置
  • strokeWidth 线的宽度
  • cap 线段末端的形状。 三种取值
    • StrokeCap.Butt平的效果(以平边开始和结束轮廓,没有延伸。)
    • StrokeCap.Round 圆形效果(以半圆延伸开始和结束轮廓)
    • StrokeCap.Square 平的效果(以半正方形延伸开始和结束轮廓)
  • pathEffect 设置显示效果(比如虚线)。实现有如下几种
    • PathEffect.cornerPathEffect(radius: Float) 将线段之间的锐角替换为指定半径的圆角 radius是半径
    • PathEffect.dashPathEffect(intervals: FloatArray, phase: Float = 0f) 将形状绘制为具有给定间隔的一系列破折号。比如虚线 例如interval={20,5},第一个参数表示虚线的长度是20,5是虚线之间的间隔是5. phase 偏移
    • PathEffect.chainPathEffect(outer: PathEffect, inner: PathEffect) 创建一个PathEffect,将内部效果应用于路径,然后应用外部效果
    • PathEffect.stampedPathEffect(shape: Path, advance: Float, phase: Float,style: StampedPathEffectStyle) 用path表示的指定形状冲压绘制的路径. shape要踩踏的路径,advance 每个冲压形状之间的前进间距, phase 在压印第一个形状之前要偏移的相位量, style如何在每个位置转换形状,因为它是冲压. style有三种取值 StampedPathEffectStyle.Translate 平移 ,StampedPathEffectStyle.Rotate 旋转,StampedPathEffectStyle.Morph 变形
  • alpha 透明度
  • colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。Image讲解里有讲到
  • blendMode 混合模式。这个后面单独讲 举例划线的例子如下:
@Preview
@Composable
fun customDrawView(){
    Canvas(modifier = Modifier.fillMaxSize(),onDraw = {
        val w = size.width
        val h = size.height
        // 蓝色的线
        drawLine(
            start = Offset(100f,100f),
            end = Offset(w-100f,100f),
            color = Color.Blue,
            strokeWidth = 10f,
            cap = StrokeCap.Square,
            alpha = 1f
        )

        // 渐变的线
        drawLine(
            brush = Brush.linearGradient(
                0.0f to Color.Red,
                0.3f to Color.Green,
                1.0f to Color.Blue,
                start = Offset(100f, 150f),
                end = Offset(w-100f, 150f),
                tileMode = TileMode.Repeated),
            start = Offset(100f,150f),
            end = Offset(w-100f,150f),
            strokeWidth = 10f,
            cap = StrokeCap.Round,
            alpha = 1f
        )

        // 横向渐变的线
        drawLine(
            brush = Brush.horizontalGradient(
                0.0f to Color.Red,
                0.3f to Color.Green,
                1.0f to Color.Blue,
                startX = 100f,
                endX = w-100f,
                tileMode = TileMode.Mirror),
            start = Offset(100f,200f),
            end = Offset(w-100f,200f),
            strokeWidth = 10f,
            cap = StrokeCap.Butt,
            alpha = 1f
        )

        // 竖直渐变的线
        drawLine(
            brush = Brush.verticalGradient(
                0.0f to Color.Red,
                0.3f to Color.Green,
                1.0f to Color.Blue,
                startY = 250f,
                endY = 350f,
                tileMode = TileMode.Clamp),
            start = Offset(100f,250f),
            end = Offset(100f,350f),
            strokeWidth = 10f,
            cap = StrokeCap.Round,
            alpha = 1f
        )

        // 横向渐变的有 pathEffect.dashPathEffect的虚线
        drawLine(
            brush = Brush.horizontalGradient(
                0.0f to Color.Red,
                0.5f to Color.Yellow,
                1.0f to Color.Blue,
                startX = 100f,
                endX = w-100f,
                tileMode = TileMode.Clamp),
            start = Offset(100f,450f),
            end = Offset(w-100f,450f),
            strokeWidth = 10f,
            cap = StrokeCap.Butt,
            alpha = 1f,
            pathEffect = PathEffect.dashPathEffect(floatArrayOf(100f,20f),10f)
        )
    })
}

效果如下: Screenshot_drawlinetest.jpg

1.2 drawRect 和 drawRoundRect 绘制矩形跟圆角矩形

DrawScope里drawRect跟drawRoundRect的代码如下:

fun drawRect(
    brush: Brush,
    topLeft: Offset = Offset.Zero,
    size: Size = this.size.offsetSize(topLeft),
    alpha: Float = 1.0f,
    style: DrawStyle = Fill,
    colorFilter: ColorFilter? = null,
    blendMode: BlendMode = DefaultBlendMode
)
fun drawRect(
    color: Color,
    topLeft: Offset = Offset.Zero,
    size: Size = this.size.offsetSize(topLeft),
    alpha: Float = 1.0f,
    style: DrawStyle = Fill,
    colorFilter: ColorFilter? = null,
    blendMode: BlendMode = DefaultBlendMode
)

fun drawRoundRect(
        brush: Brush,
        topLeft: Offset = Offset.Zero,
        size: Size = this.size.offsetSize(topLeft),
        cornerRadius: CornerRadius = CornerRadius.Zero,
        /*@FloatRange(from = 0.0, to = 1.0)*/
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)

fun drawRoundRect(
        color: Color,
        topLeft: Offset = Offset.Zero,
        size: Size = this.size.offsetSize(topLeft),
        cornerRadius: CornerRadius = CornerRadius.Zero,
        style: DrawStyle = Fill,
        /*@FloatRange(from = 0.0, to = 1.0)*/
        alpha: Float = 1.0f,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)
  • brush 刷子跟上面讲解drawline的一样
  • color 颜色
  • topLeft 左上角点的坐标
  • size 大小,比如Size(w,h) w是宽度,h是高度
  • cornerRadius 是具体的圆角
  • alpha 透明度
  • style DrawStyle 可以是Fill填充,也可以是Stroke,线条
  • colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。Image讲解里有讲到
  • blendMode 混合模式 后面讲 举例:
@Preview
@Composable
fun drawRectTest(){
    Canvas(modifier = Modifier.fillMaxSize()) {
        val w= size.width
        val h = size.height
        // 蓝底的矩形
        drawRect(
            color = Color.Blue,
            topLeft = Offset(100f,100f),
            size = Size(100f,100f),
            alpha = 1f,
            style = Fill
        )

        // 渐变的矩形
        drawRect(
            brush = Brush.linearGradient(
                0.0f to Color.Red,
                0.3f to Color.Green,
                1.0f to Color.Blue,
                start = Offset(300f, 100f),
                end = Offset(300f, 200f),
                tileMode = TileMode.Repeated),
            topLeft = Offset(300f,100f),
            size = Size(100f,100f),
            alpha = 1f,
            style = Fill
        )

        // 线框的矩形
        drawRect(
            color = Color.Blue,
            topLeft = Offset(100f,300f),
            size = Size(100f,100f),
            alpha = 1f,
            style = Stroke(width=1f,cap = StrokeCap.Butt)
        )

        // 线框的矩形
        drawRoundRect(
            color = Color.Blue,
            topLeft = Offset(300f,300f),
            size = Size(300f,100f),
            alpha = 1f,
            style = Fill,
            cornerRadius = CornerRadius(10f,10f)
        )

        // 渐变的矩形
        drawRoundRect(
            brush = Brush.linearGradient(
                0.0f to Color.Red,
                0.3f to Color.Green,
                1.0f to Color.Blue,
                start = Offset(300f, 450f),
                end = Offset(600f, 550f),
                tileMode = TileMode.Repeated),
            topLeft = Offset(300f,450f),
            size = Size(300f,100f),
            alpha = 1f,
            style = Fill,
            cornerRadius = CornerRadius(10f,10f)
        )
    }
}

效果图: Screenshot_drawrectandroundrect.jpg

1.3 drawImage 绘制图片

DrawScope里绘制图片的代码如下:

fun drawImage(
  image: ImageBitmap,
  topLeft: Offset = Offset.Zero,
  alpha: Float = 1.0f,
  style: DrawStyle = Fill,
  colorFilter: ColorFilter? = null,
  blendMode: BlendMode = DefaultBlendMode
)

fun drawImage(
    image: ImageBitmap,
    srcOffset: IntOffset = IntOffset.Zero,
    srcSize: IntSize = IntSize(image.width, image.height),
    dstOffset: IntOffset = IntOffset.Zero,
    dstSize: IntSize = srcSize,
    alpha: Float = 1.0f,
    style: DrawStyle = Fill,
    colorFilter: ColorFilter? = null,
    blendMode: BlendMode = DefaultBlendMode
)
  • image 图片
  • topLeft 左上角
  • alpha 透明度
  • style 绘制类型是Fill还是Stoke
  • colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。Image讲解里有讲到
  • blendMode 混合模式后面讲
  • srcOffset IntOffset类型原图像的偏移
  • srcSize IntSize类型 原图像的大小
  • dstOffset IntOffset 类型目标图像的左上角的位置
  • dstSize IntSize大小 目标图像的大小 举例:
@Preview
@Composable
fun drawImageTest(){
    val imageBitmap = ImageBitmap.imageResource(id = R.drawable.icon_head)
    Canvas(modifier = Modifier.fillMaxSize()) {
        val w= size.width
        val h = size.height

        drawImage(
            image = imageBitmap,
            topLeft = Offset(50f,50f),
            alpha = 1f,
            style = Fill
        )

        drawImage(
            image = imageBitmap,
            srcOffset = IntOffset(0,0),
            srcSize = IntSize(imageBitmap.width,imageBitmap.height),
            dstOffset = IntOffset(50,imageBitmap.height+100),
            dstSize = IntSize(200,200),
            blendMode = BlendMode.SrcOver
        )
    }
}

效果图:

Screenshot_drawimage.jpg

1.4 drawCircle绘制圆形

DrawScope里drawCircle的代码如下:

fun drawCircle(
        brush: Brush,
        radius: Float = size.minDimension / 2.0f,
        center: Offset = this.center,
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)

fun drawCircle(
        color: Color,
        radius: Float = size.minDimension / 2.0f,
        center: Offset = this.center,
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)
  • brush 刷子跟上面一致
  • color 颜色
  • radius 半径
  • center 圆形
  • alpha 透明度
  • style 填充方式 Fill跟Stroke
  • colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。Image讲解里有讲到
  • blendMode 混合模式 后面讲

举例:

@Preview
@Composable
fun drawCircleTest(){
    Canvas(modifier = Modifier.fillMaxSize()) {
        val w= size.width
        val h = size.height

        drawCircle(
            color = Color.Red,
            radius = 100f,
            center = Offset(150f,150f),
            alpha = 1f,
            style = Fill
        )

        drawCircle(
            color = Color.Red,
            radius = 100f,
            center = Offset(400f,150f),
            alpha = 1f,
            style = Stroke(width = 5f)
        )

        drawCircle(
            brush = Brush.radialGradient(
                0.0f to Color.Red,
                0.5f to Color.Green,
                1.0f to Color.Blue,
                center = Offset(150f,360f),
                radius = 100f,
                tileMode = TileMode.Clamp
            ),
            radius = 100f,
            center = Offset(150f,360f),
            alpha = 1f,
            style = Fill
        )
    }
}

效果图: Screenshot_drawcircle.jpg

1.5 drawOval绘制椭圆形

DrawScope中drawOval的代码:

fun drawOval(
        brush: Brush,
        topLeft: Offset = Offset.Zero,
        size: Size = this.size.offsetSize(topLeft),
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)

fun drawOval(
        color: Color,
        topLeft: Offset = Offset.Zero,
        size: Size = this.size.offsetSize(topLeft),
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)
  • brush 刷子跟上面一致
  • color 颜色
  • topLeft 左上角的坐标
  • size 大小
  • alpha 透明度
  • style 填充类型
  • colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。Image讲解里有讲到
  • blendMode 混合模式 后面讲 举例:
@Preview
@Composable
fun drawOvalTest(){
    Canvas(modifier = Modifier.fillMaxSize()) {
        val w= size.width
        val h = size.height

        drawOval(
            color = Color.Red,
            topLeft = Offset(50f,50f),
            size = Size(200f,100f),
            alpha = 1f,
            style = Stroke(width = 5f)
        )

        drawOval(
            color = Color.Red,
            topLeft = Offset(300f,50f),
            size = Size(200f,100f),
            alpha = 1f,
            style = Fill
        )

        drawOval(
            brush = Brush.horizontalGradient(
                0.0f to Color.Red,
                0.5f to Color.Green,
                1.0f to Color.Blue,
                startX = 50f,
                endX = 250f,
            ),
            topLeft = Offset(50f,180f),
            size = Size(200f,100f),
            alpha = 1f,
            style = Fill
        )
    }
}

效果图: Screenshot_drawoval.jpg

1.6 drawArc 绘制弧跟扇形

DrawScope中drawArc代码如下:

fun drawArc(
        brush: Brush,
        startAngle: Float,
        sweepAngle: Float,
        useCenter: Boolean,
        topLeft: Offset = Offset.Zero,
        size: Size = this.size.offsetSize(topLeft),
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)

fun drawArc(
        color: Color,
        startAngle: Float,
        sweepAngle: Float,
        useCenter: Boolean,
        topLeft: Offset = Offset.Zero,
        size: Size = this.size.offsetSize(topLeft),
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)
  • brush 刷子
  • color 颜色
  • startAngle 开始的角度
  • sweepAngle 划过的角度
  • useCenter 是否连接圆心
  • topLeft 左上角的位置
  • size 大小
  • alpha 透明度
  • style 填充模式
  • colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。Image讲解里有讲到
  • blendMode 混合模式 后面讲 举例:
@Preview
@Composable
fun drawArcTest(){
        Canvas(modifier = Modifier.fillMaxSize()) {
        val w= size.width
        val h = size.height

        drawArc(
            color = Color.Red,
            startAngle = 90f,
            sweepAngle = 100f,
            useCenter = false,
            alpha = 1f,
            style = Fill,
            topLeft = Offset(50f,50f),
            size = Size(200f,200f)
        )

        drawArc(
            color = Color.Red,
            startAngle = 0f,
            sweepAngle = 100f,
            useCenter = true,
            alpha = 1f,
            style = Fill,
            topLeft = Offset(150f,50f),
            size = Size(200f,200f)
        )

        drawArc(
            color = Color.Red,
            startAngle = 0f,
            sweepAngle = 100f,
            useCenter = false,
            alpha = 1f,
            style = Stroke(width = 5f),
            topLeft = Offset(300f,50f),
            size = Size(200f,200f)
        )

        drawArc(
            color = Color.Red,
            startAngle = 0f,
            sweepAngle = 100f,
            useCenter = true,
            alpha = 1f,
            style = Stroke(width = 5f),
            topLeft = Offset(500f,50f),
            size = Size(200f,200f)
        )

        drawArc(
            brush = Brush.horizontalGradient(
                0.0f to Color.Red,
                0.5f to Color.Green,
                1.0f to Color.Blue,
                startX = 50f,
                endX = 250f,
            ),
            startAngle = 0f,
            sweepAngle = 100f,
            useCenter = true,
            alpha = 1f,
            style = Stroke(width = 5f),
            topLeft = Offset(50f,350f),
            size = Size(200f,200f)
        )

        drawArc(
            brush = Brush.horizontalGradient(
                    0.0f to Color.Red,
                    0.5f to Color.Green,
                    1.0f to Color.Blue,
                    startX = 200f,
                    endX = 450f,
            ),
            startAngle = 0f,
            sweepAngle = 100f,
            useCenter = true,
            alpha = 1f,
            style = Fill,
            topLeft = Offset(200f,350f),
            size = Size(200f,200f)
        )
    }
}

效果图如下: Screenshot_drawarc.jpg

1.7 drawPath 绘制路径

fun drawPath(
        path: Path,
        color: Color,
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)

fun drawPath(
        path: Path,
        brush: Brush,
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)
  • path 路径
  • brush 刷子
  • color 颜色
  • alpha 透明度
  • style 填充类型
  • colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。Image讲解里有讲到
  • blendMode 混合模式 举例:
@Preview
@Composable
fun drawPathTest(){
    Canvas(modifier = Modifier.fillMaxSize()) {
        val path = Path()
        path.moveTo(50f,50f)
        path.lineTo(50f,150f)
        path.lineTo(200f,50f)
        path.close()
        drawPath(
            path = path,
            color = Color.Red
        )

        path.moveTo(50f,200f)
        path.lineTo(50f,350f)
        path.lineTo(200f,200f)
        path.close()
        drawPath(
            path = path,
            color = Color.Red,
            style = Stroke(width = 4f)
        )
    }
}

效果图如下:

Screenshot_drawpath.jpg

1.8 drawPoints 绘制点

fun drawPoints(
        points: List<Offset>,
        pointMode: PointMode,
        color: Color,
        strokeWidth: Float = Stroke.HairlineWidth,
        cap: StrokeCap = StrokeCap.Butt,
        pathEffect: PathEffect? = null,
        alpha: Float = 1.0f,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)

fun drawPoints(
        points: List<Offset>,
        pointMode: PointMode,
        brush: Brush,
        strokeWidth: Float = Stroke.HairlineWidth,
        cap: StrokeCap = StrokeCap.Butt,
        pathEffect: PathEffect? = null,
        alpha: Float = 1.0f,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
)
  • points 点的集合
  • pointMode 用于指示如何绘制点。有三种取值PointMode.Points 分别画点,PointMode.Lines 画线(点集合两两组合划线,奇数的话最后一个不管),PointMode.Polygon 画多边形
  • color 颜色
  • brush 刷子 设置渐变
  • strokeWidth 宽度
  • pathEffect 跟上面drawLine的一致
  • alpha 透明度
  • colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。Image讲解里有讲到
  • blendMode 混合模式 举例:
@Preview
@Composable
fun drawPointsTest(){
    Canvas(modifier = Modifier.fillMaxSize()) {
        val points = ArrayList<Offset>().apply {
            add(Offset(50f,50f))
            add(Offset(100f,50f))
            add(Offset(100f,100f))
            add(Offset(80f,100f))
        }

        val points2 = ArrayList<Offset>().apply {
            add(Offset(50f,250f))
            add(Offset(100f,250f))
            add(Offset(100f,300f))
            add(Offset(80f,300f))
            add(Offset(300f,300f))
        }

        val points3 = ArrayList<Offset>().apply {
            add(Offset(250f,250f))
            add(Offset(300f,250f))
            add(Offset(300f,300f))
            add(Offset(280f,300f))
            add(Offset(250f,250f))
        }

        drawPoints(
            points = points,
            pointMode = PointMode.Points,
            color = Color.Blue,
            strokeWidth = 15f,
            alpha = 1f
        )

        drawPoints(
            points = points2,
            pointMode = PointMode.Lines,
            color = Color.Blue,
            strokeWidth = 5f,
            alpha = 1f
        )

        drawPoints(
            points = points3,
            pointMode = PointMode.Polygon,
            color = Color.Blue,
            strokeWidth = 5f,
            cap = StrokeCap.Round,
            alpha = 1f
        )
    }
}

效果如下:

drawpoints.png

1.9 inset 平移坐标

inset是将DrawScope坐标空间平移,inset的代码如下:

inline fun DrawScope.inset(
    left: Float,
    top: Float,
    right: Float,
    bottom: Float,
    block: DrawScope.() -> Unit
){...}

inline fun DrawScope.inset(
    horizontal: Float = 0.0f,
    vertical: Float = 0.0f,
    block: DrawScope.() -> Unit
){...}

inline fun DrawScope.inset(
    inset: Float,
    block: DrawScope.() -> Unit
){...}
  • left左边平移多少
  • top 顶部平移多少
  • right 右边平移多少
  • bottom 底部平移多少
  • horizontal 横向平移多少
  • vertical 竖向平移多少
  • inset 我们通过一个例子:绘制一个矩形,宽高是分别是屏幕宽高的一半,同时绘制一个inset了屏幕一半宽高的矩形。代码如下:
@Preview
@Composable
fun drawInsetTest(){
    Canvas(modifier = Modifier.fillMaxSize()){
        val canvasQuadrantSize = size / 2F
        drawRect(
            color = Color.Green,
            size = canvasQuadrantSize
        )

        inset(canvasQuadrantSize.width,canvasQuadrantSize.height){
            drawRect(
                color = Color.Red,
                size = canvasQuadrantSize
            )
        }
    }
}

效果如图:左上角的是正常绘制的矩形,右下角的是通过inset平移了的 Screenshot_drawinset.jpg

2.0 translate 平移坐标

translate平移坐标,代码如下:

inline fun DrawScope.translate(
    left: Float = 0.0f,
    top: Float = 0.0f,
    block: DrawScope.() -> Unit
){...}
  • left 左边平移多少
  • top顶部平移多少 举例:
@Preview
@Composable
fun drawTranslateTest(){
    Canvas(modifier = Modifier.fillMaxSize()){
        val canvasQuadrantSize = size / 2F
        translate(canvasQuadrantSize.width,0f){
            drawRect(
                color = Color.Blue,
                size = canvasQuadrantSize
            )
        }
    }
}

效果如下: Screenshot_translate.jpg

2.1 rotate,rotateRad 旋转坐标

rotate,和rotateRad都是旋转,但是rotate的是旋转了多少角度,rotateRad是旋转了多少弧度。,代码如下:

inline fun DrawScope.rotate(
    degrees: Float,
    pivot: Offset = center,
    block: DrawScope.() -> Unit
){...}

inline fun DrawScope.rotateRad(
    radians: Float,
    pivot: Offset = center,
    block: DrawScope.() -> Unit
){...}
  • degrees 顺时针旋转的角度
  • pivot 旋转的中心点 (默认是图形的中心)
  • radians 顺时针旋转的弧度
  • pivot 旋转的中心点(默认是图形的中心) 举例:
@Preview
@Composable
fun drawRotateTest(){
    Canvas(modifier = Modifier.fillMaxSize()){
        val canvasSize = size
        val canvasWidth = size.width
        val canvasHeight = size.height
        rotate(degrees = 45F){
            drawRect(
                color = Color.Gray,
                topLeft = Offset(x = canvasWidth / 3F , y = canvasHeight / 3F),
                size = canvasSize / 3F
            )
        }
    }
}

@Preview
@Composable
fun drawRotateRabTest(){
    Canvas(modifier = Modifier.fillMaxSize()){
        val canvasSize = size
        val canvasWidth = size.width
        val canvasHeight = size.height
        rotateRad(45F){
            drawRect(
                color = Color.Red,
                topLeft = Offset(x = canvasWidth / 3F , y = canvasHeight / 3F),
                size = canvasSize / 3F
            )
        }
    }
}

drawRotateTest的效果如下,drawRotateRabTest的可以自行运行代码查看效果 Screenshot_rotate.jpg

2.2 scale 缩放坐标

scale 是缩放坐标,代码如下:

inline fun DrawScope.scale(
    scale: Float,
    pivot: Offset = center,
    block: DrawScope.() -> Unit
){...}

inline fun DrawScope.scale(
    scaleX: Float,
    scaleY: Float,
    pivot: Offset = center,
    block: DrawScope.() -> Unit
){...}
  • scale 缩放的大小
  • pivot 缩放的中心点
  • scaleX X轴缩放多少
  • scaleY Y轴缩放所少
  • pivot 缩放的中心点 举例:
@Preview
@Composable
fun scaleTest(){
    Canvas(modifier = Modifier.fillMaxSize()){
        val canvasSize = size
        val canvasWidth = size.width
        val canvasHeight = size.height
        
        scale(scale =0.5f){
            drawRect(
                color = Color.Gray,
                topLeft = Offset(x = canvasWidth / 3F , y = canvasHeight / 3F),
                size = canvasSize / 3F
            )
        }
    }
}

效果图如下: Screenshot_scale.jpg

2.3 clipRect 裁剪矩形区域

clipRect 是裁剪出一块矩形的区域,代码如下:

inline fun DrawScope.clipRect(
    left: Float = 0.0f,
    top: Float = 0.0f,
    right: Float = size.width,
    bottom: Float = size.height,
    clipOp: ClipOp = ClipOp.Intersect,
    block: DrawScope.() -> Unit
)
  • left 左边的坐标
  • top 顶部的坐标
  • right 右边的坐标
  • bottom 底部的坐标
  • clipOp 裁剪的类型ClipOp ClipOp.Intersect是裁剪出来的矩形。ClipOp.Difference从当前剪辑中减去提供的矩形 举例:比如绘制整个屏幕大小的矩形。但是我们设置了裁剪,代码如下:
@Preview
@Composable
fun clipRectTest(){
    Canvas(modifier = Modifier.fillMaxSize()){
        val canvasSize = size
        val canvasWidth = size.width