Skip to content

Commit ee78bf4

Browse files
Sam AdamsSam Adams
authored andcommitted
WIP: album color gradient for waveform
The effect is neat but not super noticable / pleasing. Dependencies on color-thief and multiple.js. HACK: I have hand-copied the `multiple.css` file over to my resources; an automated build step to copy it over from node_modules would be better.
1 parent cc3266b commit ee78bf4

File tree

8 files changed

+1003
-2470
lines changed

8 files changed

+1003
-2470
lines changed

‎package-lock.json‎

Lines changed: 884 additions & 2450 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
"ci": "npx shadow-cljs compile karma-test && npx karma start --single-run --reporters junit,dots"
99
},
1010
"dependencies": {
11+
"colorthief": "^2.3.2",
1112
"highlight.js": "10.7.1",
13+
"multiple.js": "0.0.1",
14+
"node-vibrant": "^3.2.1-alpha.1",
1215
"react": "17.0.2",
1316
"react-dom": "17.0.2",
1417
"spotify-web-api-js": "^1.5.2"

‎resources/public/index.html‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
}(window.location))
4545
</script>
4646
<!-- End Single Page Apps for GitHub Pages -->
47-
47+
48+
<link href="./multiple.css" rel="stylesheet">
4849
<script src="/js/compiled/app.js"></script>
4950
</body>
5051
</html>

‎resources/public/multiple.css‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
.multiple-desktop {
2+
background-size: cover;
3+
background-position: center;
4+
background-attachment: fixed;
5+
background-repeat: no-repeat;
6+
}
7+
8+
/* http://nimbupani.com/using-background-clip-for-text-with-css-fallback.html */
9+
.multiple-desktop-text {
10+
background: -webkit-linear-gradient(transparent, transparent);
11+
background: -o-linear-gradient(transparent, transparent);
12+
-webkit-background-clip: text;
13+
-webkit-text-fill-color: transparent;
14+
background-size: cover;
15+
background-position: center;
16+
background-attachment: fixed;
17+
background-repeat: no-repeat;
18+
}
19+
20+
.multiple-mobile-wrapper {
21+
position: relative;
22+
height: 100%;
23+
}
24+
25+
/* http://stackoverflow.com/a/23859719/1221082
26+
* http://stackoverflow.com/a/23795792/1221082
27+
*/
28+
.multiple-mobile {
29+
/* old browsers */
30+
clip: rect(0 auto auto 0);
31+
clip: rect(0, auto, auto, 0);
32+
/* ios workaround */
33+
-webkit-mask-image: -webkit-linear-gradient(top, #fff 0%, #fff 100%);
34+
/* new browsers */
35+
-webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
36+
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
37+
overflow: hidden;
38+
39+
position: absolute;
40+
top: 0;
41+
left: 0;
42+
width: 100%;
43+
height: 100%;
44+
45+
z-index: -1;
46+
}
47+
48+
.multiple-mobile-content {
49+
height: 100%;
50+
}
51+
52+
.multiple-mobile:before {
53+
content: '';
54+
55+
background-size: cover;
56+
background-position: center;
57+
background-repeat: no-repeat;
58+
59+
position: fixed;
60+
top: 0;
61+
right: 0;
62+
bottom: 0;
63+
left: 0;
64+
}

‎src/practaid/db.cljs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
;; TODO
5858
(s/def ::track-analysis any?)
5959

60+
(s/def ::album-colors (s/nilable (s/coll-of
61+
(s/coll-of integer?))))
62+
6063
(s/def ::player-pos-query-interval-id (s/nilable any?))
6164

6265
(s/def ::is-seeking boolean?)
@@ -123,6 +126,7 @@
123126
:external-playback-state nil
124127
:track-analysis nil
125128
:recently-played nil
129+
:album-colors nil
126130

127131
;; Player ----------------------------------------------
128132
:player nil

‎src/practaid/events.cljs‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
[reitit.frontend.easy :as rfe]
99
[reitit.frontend.controllers :as rfc]
1010
[cljs.core.async :refer [go <!]]
11-
[cljs.core.async.interop :refer-macros [<p!]])
12-
(:require ["spotify-web-api-js" :as SpotifyWebApi]
13-
[cljs.spec.alpha :as s]))
11+
[cljs.core.async.interop :refer-macros [<p!]]
12+
[cljs.spec.alpha :as s]
13+
["colorthief/dist/color-thief.mjs" :default ColorThief]))
1414

1515

1616
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -239,6 +239,15 @@
239239

240240
;; Looper page---------------------------------------------
241241

242+
(rf/reg-event-fx
243+
::album-cover-img-loaded
244+
[check-db-spec-interceptor]
245+
(fn [{:keys [db]} [_ img-element]]
246+
(let [palette (-> (new ColorThief)
247+
(. getPalette img-element 2)
248+
(js->clj))]
249+
{:db (assoc db :album-colors palette)})))
250+
242251
(rf/reg-event-fx
243252
::seek-player
244253
[check-db-spec-interceptor]

‎src/practaid/subs.cljs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@
7272
(fn [db]
7373
(q/is-paused db)))
7474

75+
(rf/reg-sub
76+
::album-colors
77+
(fn [db]
78+
(:album-colors db)))
79+
7580
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7681
;; Tier 2
7782
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

‎src/practaid/views/looper_page.cljs‎

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
[spade.core :refer [defclass defkeyframes]]
44
[re-frame.core :as rf]
55
[clojure.string :as str]
6-
[practaid.player :refer [playback-pos-refresh-interval-ms]]))
6+
[practaid.player :refer [playback-pos-refresh-interval-ms]]
7+
["multiple.js" :as Multiple]))
78

89
(defclass playback-metadata-style []
910
{:display "flex"
@@ -28,7 +29,11 @@
2829
[:div {:class (playback-metadata-style)}
2930
(and album-cover-url
3031
[:div.album-cover-container
31-
[:img.album-cover-image {:src album-cover-url}]])
32+
[:img.album-cover-image {:src album-cover-url
33+
:crossOrigin "Anonymous"
34+
:on-load #(rf/dispatch [:practaid.events/album-cover-img-loaded
35+
(-> js/document
36+
(. querySelector "img.album-cover-image"))])}]])
3237
[:div.text-metadata-container
3338
[:a {:href (str "https://open.spotify.com/track/" track-id)
3439
:title "Play on Spotify"}
@@ -111,18 +116,24 @@
111116
;(defkeyframes)
112117

113118

114-
(defn waveform [{:keys [loudnesses loop-start-frac loop-end-frac player-pos-frac handle-click should-smooth-motion]}]
115-
[:div {:class (waveform-style)
116-
:on-click handle-click}
117-
[waveform-pos-marker {:location loop-start-frac :color "black"}]
118-
[waveform-pos-marker {:location loop-end-frac :color "black"}]
119-
[playback-pos-marker {:location player-pos-frac
120-
:should-smooth-motion should-smooth-motion}]
121-
(for [[i loudness] (map-indexed vector loudnesses)]
122-
[:div.wave {:key i
123-
:class (wave-style)
124-
;; TODO move me?
125-
:style {:height (str (int (* loudness 100)) "%")}}])])
119+
(defn waveform [{:keys [loudnesses loop-start-frac loop-end-frac player-pos-frac handle-click should-smooth-motion album-colors]}]
120+
(let [rgbs (map #(str "rgb(" (str/join ", " %) ")")
121+
album-colors)
122+
background (when rgbs (str "linear-gradient(to right," (str/join ", " rgbs) ")"))
123+
waveform-style (waveform-style)
124+
_ (when rgbs (new ^js Multiple (clj->js {:selector "div.wave"
125+
:background background})))]
126+
[:div {:class waveform-style
127+
:on-click handle-click}
128+
[waveform-pos-marker {:location loop-start-frac :color "black"}]
129+
[waveform-pos-marker {:location loop-end-frac :color "black"}]
130+
[playback-pos-marker {:location player-pos-frac
131+
:should-smooth-motion should-smooth-motion}]
132+
(for [[i loudness] (map-indexed vector loudnesses)]
133+
[:div.wave {:key i
134+
:class (wave-style)
135+
;; TODO move me?
136+
:style {:height (str (int (* loudness 100)) "%")}}])]))
126137

127138

128139

@@ -181,7 +192,8 @@
181192
defaulted-loop-start-frac @(rf/subscribe [:practaid.subs/defaulted-loop-start-frac])
182193
defaulted-loop-end-frac @(rf/subscribe [:practaid.subs/defaulted-loop-end-frac])
183194
player-pos-frac @(rf/subscribe [:practaid.subs/player-pos-frac])
184-
should-smooth-motion @(rf/subscribe [:practaid.subs/should-smooth-motion])]
195+
should-smooth-motion @(rf/subscribe [:practaid.subs/should-smooth-motion])
196+
album-colors @(rf/subscribe [:practaid.subs/album-colors])]
185197
[page-wrapper
186198
[:div {:class (looper-page-style)}
187199
[:div.connection-status
@@ -210,7 +222,8 @@
210222
defaulted-loop-end-ms])
211223
:on-commit #(rf/dispatch [:practaid.events/reset-looper])
212224
:disabled (not is-playback-ours)}]
213-
[waveform {:loudnesses loudnesses
225+
[waveform {:album-colors album-colors
226+
:loudnesses loudnesses
214227
:loop-start-frac defaulted-loop-start-frac
215228
:loop-end-frac defaulted-loop-end-frac
216229
:player-pos-frac player-pos-frac

0 commit comments

Comments
 (0)