如何在 Jetpack Compose Canvas 中绘制圆角多边形?
How to draw rounded corner polygons in Jetpack Compose Canvas?
我正在尝试使用 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
,但我无法得到合适的结果。
如何画出下图这样的东西?
对于 Stroke
你可以像这样指定舍入:
drawPath(
...
style = Stroke(
width = 2.dp.toPx(),
pathEffect = PathEffect.cornerPathEffect(4.dp.toPx())
)
)
然而 Fill
似乎缺少支持四舍五入。我创建了一个feature request,请给它加注星标。
但是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)
结果:
基于@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
我正在尝试使用 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
,但我无法得到合适的结果。
如何画出下图这样的东西?
对于 Stroke
你可以像这样指定舍入:
drawPath(
...
style = Stroke(
width = 2.dp.toPx(),
pathEffect = PathEffect.cornerPathEffect(4.dp.toPx())
)
)
然而 Fill
似乎缺少支持四舍五入。我创建了一个feature request,请给它加注星标。
但是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)
结果:
基于@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