我正在使用 Jetpack Compose 构建一个颜色选择器,并尝试实现饱和度和亮度选择器菱形(矩形旋转 45 度),如图像中所示,但无法找到一个好的方法来显示他们认为的颜色看起来像
我可以在菱形中获取位置并用左侧图像绘制圆圈,因为这些是圆圈,所以它们看起来不太好。还尝试绘制小路径,但它会显着减慢应用程序的速度。
/**
* Get each point and saturation and lightness of the point. This function is for
* creating points to draw like gradient effect for HSL color
*/
fun getPointsInRhombus(length: Float): MutableList<ColorPoint> {
val step = length.toInt() / 50
val colorPoints = mutableListOf<ColorPoint>()
for (yPos in 0..length.toInt() step step) {
val range = getIntRangeInLength(length = length, yPos.toFloat())
for (xPos in range step step) {
val path = rhombusPath(Size(10f, 10f))
path.translate(Offset(xPos.toFloat() - 5, yPos.toFloat()))
val saturation = xPos / length
val lightness = 1 - (yPos / length)
val colorPoint =
ColorPoint(Offset(xPos.toFloat(), yPos.toFloat()), saturation, lightness, path)
colorPoints.add(colorPoint)
}
}
return colorPoints
}
colorPoints.forEach { colorPoint: ColorPoint ->
drawCircle(
Color.hsl(hue, colorPoint.saturation, colorPoint.lightness),
center = colorPoint.point,
radius = 10f
)
}
还尝试创建一个用于亮度的形状,另一个用于饱和度的形状,并尝试将它们混合在一起,但它不起作用,如右图所示。
with(drawContext.canvas.nativeCanvas) {
val checkPoint = saveLayer(null, null)
// Destination lightness top to bottom
drawPath(
rhombusPath, Brush.verticalGradient(
colors = listOf(
Color.hsl(
hue,
saturation = .5f,
lightness = 1f,
alpha = 1f
),
Color.hsl(
hue,
saturation = .5f,
lightness = 0f,
alpha = 1f
)
)
)
)
// Source saturation left to right
drawPath(
rhombusPath,
Brush.horizontalGradient(
colors = listOf(
Color.hsl(
hue,
saturation = 0f,
lightness = .5f,
alpha = 1f
),
Color.hsl(
hue,
saturation = 1f,
lightness = .5f,
alpha = 1f
)
)
),
blendMode = BlendMode.SrcIn
)
restoreToCount(checkPoint)
}
我需要的是将第一张图像的颜色应用于右侧的类似菱形的图像,而无需绘制圆圈或路径。我认为这可以通过一个渐变或多个渐变或混合它们来解决,但不知道如何解决。
检查了这个question in c#供引用,但不知道如何将其应用到 Compose Brush
最佳答案
对于HSL渐变,BlendMode.Multiply
不起作用,它适用于获取HSV渐变。解决方案是将 Blendmode.Overlay 与渐变结合使用。 Brush.linergradient 的默认角度是顺时针45 度,需要将其设置为0 度才能使可组合项从开始到结束的饱和度发生变化。
val lightnessGradient = remember {
Brush.verticalGradient(
colors = listOf(
Color.hsl(hue = hue, saturation = .5f, lightness = 1f),
Color.hsl(hue = hue, saturation = .5f, lightness = 0f)
)
)
}
val saturationHSLGradient = remember {
val gradientOffset = GradientOffset(GradientAngle.CW0)
Brush.linearGradient(
colors = listOf(
Color.hsl(hue, 0f, .5f),
Color.hsl(hue, 1f, .5f)
),
start = gradientOffset.start,
end = gradientOffset.end
)
}
然后使用 Overlay 的 Blend(PorterDuff) 模式在图层中绘制这两个渐变
Canvas(modifier = canvasModifier) {
drawIntoLayer {
drawPath(
path = rhombusPath,
lightnessGradient,
)
drawPath(
path = rhombusPath,
saturationHSLGradient,
blendMode = BlendMode.Overlay
)
}
}
混合绘图功能
fun DrawScope.drawIntoLayer(
content: DrawScope.() -> Unit
) {
with(drawContext.canvas.nativeCanvas) {
val checkPoint = saveLayer(null, null)
content()
restoreToCount(checkPoint)
}
}
HSV和HSL渐变的结果,不是用渐变绘制小矩形,而是在点处绘制小矩形,以验证HSL渐变与位置处的真实颜色匹配。
可用于全面实现的 Github 存储库已可用 here .
关于android - 如何使用 Jetpack Compose 创建 HSL 饱和度和亮度变化渐变或画笔编辑器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71423294/