如何在 2 条线与 Canvas 重叠时保持相同的颜色 alpha
How to keep the same color alpha when 2 lines are being overlapped with Canvas
我正在使用 Canvas
方法 drawLines(...)
并且我有 2 行 crossing/overlapping 彼此,这些行的颜色 alpha 为 0.3f。
问题是,当彼此交叉时,此 alpha 会累积,将它们的 crosspoint 转换为颜色 alpha 0.6f。
有什么办法即使交叉也能保持原来的alpha值?
没有。这是不可能的,因为我们必须修改可组合项特定“部分”的 alpha 值,这不是一件容易实现的事情。你需要改变你的方法。
第 1 步。根据起点、终点和笔画宽度创建 Path
:
fun linePath(start: Offset, end: Offset, strokeWidth: Float) =
Path().apply {
// calculations from
val size = end - start
val perpendicular = Offset(size.y, -size.x)
val length = hypot(size.x, size.y)
val normalized = Offset(perpendicular.x / length, perpendicular.y / length)
val points = listOf(
end + normalized * strokeWidth / 2f,
start + normalized * strokeWidth / 2f,
start - normalized * strokeWidth / 2f,
end - normalized * strokeWidth / 2f,
)
moveTo(points.last())
points.forEach(::lineTo)
}
fun Path.moveTo(offset: Offset) =
moveTo(offset.x, offset.y)
fun Path.lineTo(offset: Offset) =
lineTo(offset.x, offset.y)
第 2 步。使用 clipPath
绘制需要的部分线:
Canvas(Modifier.fillMaxSize()) {
val rect = Rect(Offset.Zero, size)
val firstLinePath = linePath(
start = rect.topLeft,
end = rect.bottomRight,
strokeWidth = 20f,
)
val firstLineColor = Color.Red
val secondLinePath = linePath(
start = rect.topRight,
end = rect.bottomLeft,
strokeWidth = 20f,
)
val secondLineColor = Color.Green
val sharedAlpha = 0.5f
// draw first line without intersection part
clipPath(secondLinePath, clipOp = ClipOp.Difference) {
drawPath(firstLinePath, color = firstLineColor.copy(sharedAlpha))
}
// draw second line without intersection part
clipPath(firstLinePath, clipOp = ClipOp.Difference) {
drawPath(secondLinePath, color = secondLineColor.copy(sharedAlpha))
}
// draw intersection part with mixed color
clipPath(secondLinePath) {
val blendedColor = Color(
ColorUtils.blendARGB(
firstLineColor.toArgb(),
secondLineColor.toArgb(),
0.5f
)
)
drawPath(firstLinePath, color = blendedColor.copy(sharedAlpha))
}
}
结果:
我正在使用 Canvas
方法 drawLines(...)
并且我有 2 行 crossing/overlapping 彼此,这些行的颜色 alpha 为 0.3f。
问题是,当彼此交叉时,此 alpha 会累积,将它们的 crosspoint 转换为颜色 alpha 0.6f。
有什么办法即使交叉也能保持原来的alpha值?
没有。这是不可能的,因为我们必须修改可组合项特定“部分”的 alpha 值,这不是一件容易实现的事情。你需要改变你的方法。
第 1 步。根据起点、终点和笔画宽度创建 Path
:
fun linePath(start: Offset, end: Offset, strokeWidth: Float) =
Path().apply {
// calculations from
val size = end - start
val perpendicular = Offset(size.y, -size.x)
val length = hypot(size.x, size.y)
val normalized = Offset(perpendicular.x / length, perpendicular.y / length)
val points = listOf(
end + normalized * strokeWidth / 2f,
start + normalized * strokeWidth / 2f,
start - normalized * strokeWidth / 2f,
end - normalized * strokeWidth / 2f,
)
moveTo(points.last())
points.forEach(::lineTo)
}
fun Path.moveTo(offset: Offset) =
moveTo(offset.x, offset.y)
fun Path.lineTo(offset: Offset) =
lineTo(offset.x, offset.y)
第 2 步。使用 clipPath
绘制需要的部分线:
Canvas(Modifier.fillMaxSize()) {
val rect = Rect(Offset.Zero, size)
val firstLinePath = linePath(
start = rect.topLeft,
end = rect.bottomRight,
strokeWidth = 20f,
)
val firstLineColor = Color.Red
val secondLinePath = linePath(
start = rect.topRight,
end = rect.bottomLeft,
strokeWidth = 20f,
)
val secondLineColor = Color.Green
val sharedAlpha = 0.5f
// draw first line without intersection part
clipPath(secondLinePath, clipOp = ClipOp.Difference) {
drawPath(firstLinePath, color = firstLineColor.copy(sharedAlpha))
}
// draw second line without intersection part
clipPath(firstLinePath, clipOp = ClipOp.Difference) {
drawPath(secondLinePath, color = secondLineColor.copy(sharedAlpha))
}
// draw intersection part with mixed color
clipPath(secondLinePath) {
val blendedColor = Color(
ColorUtils.blendARGB(
firstLineColor.toArgb(),
secondLineColor.toArgb(),
0.5f
)
)
drawPath(firstLinePath, color = blendedColor.copy(sharedAlpha))
}
}
结果: