From e0e1b0d9a3c87b9f2fa05f0144c3528ffa2db0aa Mon Sep 17 00:00:00 2001 From: Sander Date: Sat, 24 Aug 2024 14:16:40 +0400 Subject: [PATCH] feat: implement oklch --- src/Color/Interpolate.elm | 33 ++++++++++++++++++----- src/Color/OkLch.elm | 55 +++++++++++++++++++++++++++++++++++++++ src/Color/Rgb.elm | 2 ++ src/Draw.elm | 22 +++++++--------- 4 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 src/Color/OkLch.elm diff --git a/src/Color/Interpolate.elm b/src/Color/Interpolate.elm index 528e0cf..63dabb9 100644 --- a/src/Color/Interpolate.elm +++ b/src/Color/Interpolate.elm @@ -20,19 +20,38 @@ float start end time = hue : Float -> Float -> Float -> Float -hue a b = +hue a b t = let + ha = + normalizeHue a + + hb = + normalizeHue b + + -- Calculate the shortest distance between hues d = - if b > a && b - a > 180 then - b - a + 360 + if abs (hb - ha) <= 180 then + hb - ha - else if b < a && a - b > 180 then - b + 360 - a + else if hb > ha then + (hb - 360) - ha else - b - a + (hb + 360) - ha in - linear a d + normalizeHue (linear a d t) + + +normalizeHue : Float -> Float +normalizeHue h = + if h < 0 then + normalizeHue (h + 360) + + else if h > 360 then + normalizeHue (h - 360) + + else + h scaleProgress : Int -> Float -> ( Int, Int, Float ) diff --git a/src/Color/OkLch.elm b/src/Color/OkLch.elm new file mode 100644 index 0000000..5898ac7 --- /dev/null +++ b/src/Color/OkLch.elm @@ -0,0 +1,55 @@ +module Color.OkLch exposing (..) + +import Color.Interpolate as Interpolate + + +type alias OkLch = + { l : Float + , c : Float + , h : Float + , a : Maybe Float + } + + + +-- Interpolate + + +interpolate : OkLch -> OkLch -> Float -> OkLch +interpolate a b time = + { l = Interpolate.float a.l b.l time + , c = Interpolate.float a.c b.c time + , h = Interpolate.hue a.h b.h time + , a = Maybe.map2 (\aa ba -> Interpolate.float aa ba time) a.a b.a + } + + +interpolateLong : OkLch -> OkLch -> Float -> OkLch +interpolateLong a b time = + { l = Interpolate.float a.l b.l time + , c = Interpolate.float a.c b.c time + , h = Interpolate.normalizeHue (Interpolate.float a.h b.h time) + , a = Maybe.map2 (\aa ba -> Interpolate.float aa ba time) a.a b.a + } + + + +-- Serialize + + +toString : OkLch -> String +toString { l, c, h, a } = + "oklch(" + ++ String.fromFloat l + ++ "% " + ++ String.fromFloat c + ++ " " + ++ String.fromFloat h + ++ (case a of + Just aa -> + " / " ++ String.fromFloat aa + + Nothing -> + "" + ) + ++ ")" diff --git a/src/Color/Rgb.elm b/src/Color/Rgb.elm index b75caab..53f0d1e 100644 --- a/src/Color/Rgb.elm +++ b/src/Color/Rgb.elm @@ -23,6 +23,7 @@ interpolate rgb1 rgb2 time = -- Serialize +toString : RGB -> String toString { r, g, b } = "rgb(" ++ String.fromFloat r @@ -33,6 +34,7 @@ toString { r, g, b } = ++ ")" +toP3String : RGB -> String toP3String { r, g, b } = "color(display-p3 " ++ String.fromFloat (r / 255) diff --git a/src/Draw.elm b/src/Draw.elm index 34178bb..9a63131 100644 --- a/src/Draw.elm +++ b/src/Draw.elm @@ -5,6 +5,7 @@ import Clock import Color.Interpolate as Interpolate import Color.Lab as Lab exposing (Lab) import Color.Lch as Lch exposing (Lch) +import Color.OkLch as OkLch import Color.Rgb as Rgb import Cons exposing (cons) import Svg exposing (Svg) @@ -135,11 +136,13 @@ groupOfTicks clockArms = List.concatMap ticksAlongTrack clockArms -colorFill : Float -> Lch -colorFill = - Lch.interpolateLong - { l = 92.991667, c = 47.85505, h = -30 } - { l = 92.991667, c = 47.85505, h = 330 } +colorFill : Float -> String +colorFill progress = + OkLch.toString <| + OkLch.interpolateLong + { l = 98.0, c = 0.13, h = 60.0, a = Nothing } + { l = 98.0, c = 0.13, h = 320.0, a = Nothing } + progress singleArm : Clock.Arm -> Bool -> Float -> Svg msg @@ -151,9 +154,6 @@ singleArm { radius, armRadius, animatedAngle } supportsP3Color delta = progress = newAngle / 360 - fill = - (Lch.toLab >> Lab.toRgb) <| colorFill progress - ( cx, cy ) = pointOnArc 0 0 radius newAngle in @@ -170,11 +170,7 @@ singleArm { radius, armRadius, animatedAngle } supportsP3Color delta = ++ dotPath radius (newAngle - (armRadius / radius)) (0.8 * armRadius) ++ "Z" , SA.fill <| - if supportsP3Color then - Rgb.toP3String fill - - else - Rgb.toString fill + colorFill progress , SA.fillRule "evenodd" ] []