Skip to content

Commit f594544

Browse files
committed
Make swatches interactive
1 parent 0f0f98b commit f594544

File tree

3 files changed

+65
-42
lines changed

3 files changed

+65
-42
lines changed

apps/components_guide_web/assets/css/app.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,9 @@ a[aria-current=page][class*="hover\:border-"] {
6565
border-color: currentColor;
6666
}
6767

68+
[phx-hook=SwatchInput] {
69+
user-select: none;
70+
cursor: default;
71+
}
72+
6873
/* @import "./phoenix.css"; */

apps/components_guide_web/assets/js/app.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,28 @@ let csrfToken = document
1818
.querySelector("meta[name='csrf-token']")
1919
.getAttribute("content");
2020
let liveSocket = new LiveSocket("/live", Socket, {
21-
params: { _csrf_token: csrfToken }
21+
params: { _csrf_token: csrfToken },
22+
hooks: {
23+
SwatchInput: {
24+
mounted() {
25+
const mouseEventHandler = (e) => {
26+
if (e.which !== 0) {
27+
const x = e.offsetX,
28+
y = e.offsetY;
29+
const maxX = this.el.width.baseVal.value;
30+
const maxY = this.el.height.baseVal.value;
31+
const xFraction = x / maxX;
32+
const yFraction = y / maxY;
33+
const value = (xFraction + yFraction) / 2;
34+
const { colorProperty } = this.el.dataset;
35+
this.pushEvent("color_property_changed", { [colorProperty]: `${value}` });
36+
}
37+
}
38+
this.el.addEventListener("mousedown", mouseEventHandler);
39+
this.el.addEventListener("mousemove", mouseEventHandler);
40+
}
41+
}
42+
}
2243
});
2344

2445
// Show progress bar on live navigation and form submits

apps/components_guide_web/lib/components_guide_web/live/color.ex

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ defmodule ComponentsGuideWeb.ColorLive do
2323

2424
color = {:srgb, r, g, b} |> Styling.convert(:lab)
2525

26-
IO.puts("INPUT #{r} #{g} #{b} OUTPUT #{inspect(color)}")
2726
%State{color: color}
2827
end
2928

@@ -75,49 +74,33 @@ defmodule ComponentsGuideWeb.ColorLive do
7574
end
7675

7776
def render(assigns) do
78-
swatch_size = 100
77+
swatch_size = 160
7978
{:lab, l, a, b} = assigns.state.color
8079

81-
l_steps = 10
80+
gradient_steps = 20
8281

8382
l_gradient =
8483
Styling.linear_gradient(
8584
"150grad",
86-
for(n <- 0..l_steps, do: {:lab, n * (100 / l_steps), a, b})
85+
for(n <- 0..gradient_steps, do: {:lab, n * (100 / gradient_steps), a, b})
8786
)
8887

8988
l_gradient_svg =
9089
Styling.svg_linear_gradient(
9190
"rotate(45)",
92-
for(n <- 0..l_steps, do: {:lab, interpolate(n / l_steps, {0.0, 100.0}), a, b})
93-
)
94-
95-
a_steps = 10
96-
97-
a_gradient =
98-
Styling.linear_gradient(
99-
"150grad",
100-
for(n <- 0..a_steps, do: {:lab, l, interpolate(n / a_steps, {-127.0, 127.0}), b})
91+
for(n <- 0..gradient_steps, do: {:lab, interpolate(n / gradient_steps, {0.0, 100.0}), a, b})
10192
)
10293

10394
a_gradient_svg =
10495
Styling.svg_linear_gradient(
10596
"rotate(45)",
106-
for(n <- 0..a_steps, do: {:lab, l, interpolate(n / a_steps, {-127.0, 127.0}), b})
107-
)
108-
109-
b_steps = 10
110-
111-
b_gradient =
112-
Styling.linear_gradient(
113-
"150grad",
114-
for(n <- 0..b_steps, do: {:lab, l, a, interpolate(n / b_steps, {-127.0, 127.0})})
97+
for(n <- 0..gradient_steps, do: {:lab, l, interpolate(n / gradient_steps, {-127.0, 127.0}), b})
11598
)
11699

117100
b_gradient_svg =
118101
Styling.svg_linear_gradient(
119102
"rotate(45)",
120-
for(n <- 0..b_steps, do: {:lab, l, a, interpolate(n / b_steps, {-127.0, 127.0})})
103+
for(n <- 0..gradient_steps, do: {:lab, l, a, interpolate(n / gradient_steps, {-127.0, 127.0})})
121104
)
122105

123106
~L"""
@@ -126,35 +109,27 @@ defmodule ComponentsGuideWeb.ColorLive do
126109
<rect fill="<%= State.css_srgb(@state) %>" width="1" height="1" />
127110
</svg>
128111
<div class="flex">
129-
<svg viewBox="0 0 1 1" width="100" height="100">
112+
<svg viewBox="0 0 1 1" width="<%= swatch_size %>" height="<%= swatch_size %>" phx-hook=SwatchInput data-color-property=l>
130113
<defs>
131114
<%= l_gradient_svg %>
132115
</defs>
133116
<rect width="1" height="1" fill="url('#myGradient')" />
134-
<circle cx="<%= l / 100.0 %>" cy="<%= l / 100.0 %>" r="0.05" fill="white" stroke="black" stroke-width="0.01" />
117+
<circle data-drag-knob cx="<%= l / 100.0 %>" cy="<%= l / 100.0 %>" r="0.05" fill="white" stroke="black" stroke-width="0.01" />
135118
</svg>
136-
<svg viewBox="0 0 1 1" width="100" height="100">
119+
<svg viewBox="0 0 1 1" width="<%= swatch_size %>" height="<%= swatch_size %>" phx-hook=SwatchInput data-color-property=a>
137120
<defs>
138121
<%= a_gradient_svg %>
139122
</defs>
140123
<rect width="1" height="1" fill="url('#myGradient')" />
141124
<circle cx="<%= (a / 127.0) / 2.0 + 0.5 %>" cy="<%= (a / 127.0) / 2.0 + 0.5 %>" r="0.05" fill="white" stroke="black" stroke-width="0.01" />
142125
</svg>
143-
<svg viewBox="0 0 1 1" width="100" height="100">
126+
<svg viewBox="0 0 1 1" width="<%= swatch_size %>" height="<%= swatch_size %>" phx-hook=SwatchInput data-color-property=b>
144127
<defs>
145128
<%= b_gradient_svg %>
146129
</defs>
147130
<rect width="1" height="1" fill="url('#myGradient')" />
148131
<circle cx="<%= (b / 127.0) / 2.0 + 0.5 %>" cy="<%= (b / 127.0) / 2.0 + 0.5 %>" r="0.05" fill="white" stroke="black" stroke-width="0.01" />
149132
</svg>
150-
<!--<div style="width: 100px; height: 100px; background-image: <%= l_gradient %>"></div>-->
151-
<!--<div style="width: 100px; height: 100px; background-image: <%= a_gradient %>"></div>-->
152-
<div style="width: 100px; height: 100px; background-image: <%= b_gradient %>"></div>
153-
<svg width="100" height="100">
154-
<foreignObject>
155-
<div style="width: 100px; height: 100px; background-image: <%= b_gradient %>"></div>
156-
</foreignObject>
157-
</svg>
158133
</div>
159134
<form phx-change="lab_changed" class="flex flex-col">
160135
<label>
@@ -209,12 +184,8 @@ defmodule ComponentsGuideWeb.ColorLive do
209184
|> push_patch(to: Routes.color_path(socket, :lab, encoded), replace: true)}
210185
end
211186

212-
def handle_event("lab_changed", %{"l" => l, "a" => a, "b" => b}, socket) do
213-
l = l |> String.to_integer()
214-
a = a |> String.to_integer()
215-
b = b |> String.to_integer()
216-
217-
state = socket.assigns.state |> State.set_color({:lab, l, a, b})
187+
def change_color(color, socket) do
188+
state = socket.assigns.state |> State.set_color(color)
218189

219190
case socket.assigns.tref do
220191
nil -> nil
@@ -232,4 +203,30 @@ defmodule ComponentsGuideWeb.ColorLive do
232203
|> assign(:tref, tref)
233204
}
234205
end
206+
207+
def handle_event("lab_changed", %{"l" => l, "a" => a, "b" => b}, socket) do
208+
l = l |> String.to_integer()
209+
a = a |> String.to_integer()
210+
b = b |> String.to_integer()
211+
212+
{:lab, l, a, b} |> change_color(socket)
213+
end
214+
215+
def handle_event("color_property_changed", %{"l" => l}, socket) do
216+
l = (String.to_float(l) * 100) |> round()
217+
{:lab, _, a, b} = socket.assigns.state.color
218+
{:lab, l, a, b} |> change_color(socket)
219+
end
220+
221+
def handle_event("color_property_changed", %{"a" => a}, socket) do
222+
a = ((String.to_float(a) * 2 - 1.0) * 127) |> round()
223+
{:lab, l, _, b} = socket.assigns.state.color
224+
{:lab, l, a, b} |> change_color(socket)
225+
end
226+
227+
def handle_event("color_property_changed", %{"b" => b}, socket) do
228+
b = ((String.to_float(b) * 2 - 1.0) * 127) |> round()
229+
{:lab, l, a, _} = socket.assigns.state.color
230+
{:lab, l, a, b} |> change_color(socket)
231+
end
235232
end

0 commit comments

Comments
 (0)