Как создать градиент изменения насыщенности и яркости HSL или редактор кистей с помощью Jetpack Compose?
Я создаю палитру цветов с помощью Jetpack Compose и пытаюсь реализовать ромб выбора насыщенности и яркости (прямоугольник, повернутый на 45 градусов), как это видно на изображениях, но не смог найти хороший метод для отображения цветов, как они должны выглядеть
![](/images/02a651420ae37079c2d49936c432419838856b2e.png)
![](/images/ea05e8877150e48cc3473c5e016e3a28ea8268ec.png)
Я могу получить позиции в ромбе и рисовать круги с изображением слева, так как это круги, они не выглядят хорошо. Также пытался рисовать небольшие пути, но это значительно замедляет работу приложения.
/**
* 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)
}
Мне нужно, чтобы цвета с первого изображения были применены к ромбовидному изображению справа без рисования кругов или путей. Я думаю, что это можно решить с помощью одного градиента или нескольких градиентов или их смешивания, но не могу понять, как это сделать.
Проверил этот вопрос в С# для справки, но не смог понять, как применить его к Compose.
Brush
1 ответ
Для градиента HSL
BlendMode.Multiply
не работает, он работает для получения градиента HSV . Решение состоит в том, чтобы использовать Blendmode.Overlay с градиентами. Также угол по умолчанию для Brush.linergradient составляет 45 градусов по часовой стрелке, необходимо установить его на 0 градусов , чтобы насыщенность изменялась от начала до конца Composable.
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
)
}
Затем нарисуйте оба этих градиента в слое с режимом Blend(PorterDuff) Overlay.
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 для полной реализации доступен здесь .