如何在 Jetpack Compose Canvas 中绘制带有圆角的多边形?

8
我正在尝试使用Jetpack Compose中的Canvas创建圆角三角形。
我尝试使用以下代码绘制三角形:
@Composable
fun RoundedTriangle() {
    Canvas(modifier = Modifier.size(500.dp)) {
        val trianglePath = Path().apply {
            val height = size.height
            val width = size.width
            moveTo(width / 2.0f, 0f)
            lineTo(width, height)
            lineTo(0f, height)
        }
            drawPath(trianglePath, color = Color.Blue)
    }
}

我不知道如何将三角形的边角弄成圆角。我尝试使用arcTo,但是无法得到合适的结果。

我该如何绘制类似下图的形状?

enter image description here

2个回答

13

对于Stroke,您可以像这样指定圆角:

drawPath(
    ...
    style = Stroke(
        width = 2.dp.toPx(),
        pathEffect = PathEffect.cornerPathEffect(4.dp.toPx())
    )
)

然而,Fill似乎缺乏支持四舍五入的功能。我已经创建了一个特性请求,请点赞。

但是Canvas有一个drawOutline函数,它接受Outline(可以包装一个Path)和Paint,你可以为其指定pathEffect

Canvas(modifier = Modifier.fillMaxWidth().aspectRatio(1f)) {
    val rect = Rect(Offset.Zero, size)
    val trianglePath = Path().apply {
        moveTo(rect.topCenter)
        lineTo(rect.bottomRight)
        lineTo(rect.bottomLeft)
        close()
    }

    drawIntoCanvas { canvas ->
        canvas.drawOutline(
            outline = Outline.Generic(trianglePath),
            paint = Paint().apply {
                color = Color.Black
                pathEffect = PathEffect.cornerPathEffect(rect.maxDimension / 3)
            }
        )
    }
}

Path 助手:

fun Path.moveTo(offset: Offset) = moveTo(offset.x, offset.y)
fun Path.lineTo(offset: Offset) = lineTo(offset.x, offset.y)

结果:


你知道这个怎么应用到正方形上吗? - AouledIssa
1
@AouledIssa 只需在路径中添加一个点,例如像这样 - Phil Dukhov
true 仅仅会给你一个 super circle 或者平滑的圆角效果。 - AouledIssa
@AouledIssa同意使用close()会使代码看起来更加简洁。 - Phil Dukhov
1
@RaymondArteaga 是的,这是一个不同的问题。我想你可以手绘它,例如使用addArc创建Path,并参考这个答案 - Phil Dukhov
显示剩余3条评论

1

根据@philip-dukhov的回答,如果有人想将其应用于正方形

@Composable
fun SquirclePath(
    modifier: Modifier,
    smoothingFactor: Int = 60,
    color: Color,
    strokeWidth: Float,
) {
    Canvas(
        modifier = modifier
    ) {
        val rect = Rect(Offset.Zero, size)
        val percent = smoothingFactor.percentOf(rect.minDimension)
        val squirclePath = Path().apply {
            with(rect) {
                lineTo(topRight)
                lineTo(bottomRight)
                lineTo(bottomLeft)
                lineTo(topLeft)
                // this is where the path is finally linked together
                close()
            }
        }

        drawIntoCanvas { canvas ->
            canvas.drawOutline(
                outline = Outline.Generic(squirclePath),
                paint = Paint().apply {
                    this.color = color
                    this.style = PaintingStyle.Fill
                    this.strokeWidth = strokeWidth
                    pathEffect = PathEffect.cornerPathEffect(percent)
                }
            )
        }
    }
}

fun Int.percentOf(target:Float) = (this.toFloat() / 100) * target

@philip-dukhov 我无法将整个代码放入评论中,所以我在这里发布了它。 - AouledIssa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接