diff --git a/report.html b/report.html new file mode 100644 index 0000000..db1919e --- /dev/null +++ b/report.html @@ -0,0 +1,846 @@ + +[app] Build Report - shadow-cljs
\ No newline at end of file diff --git a/resources/public/index.html b/resources/public/index.html index 032ac86..1a159d3 100644 --- a/resources/public/index.html +++ b/resources/public/index.html @@ -7,8 +7,6 @@
- diff --git a/resources/public/style.css b/resources/public/style.css index 832142d..6ffed1d 100644 --- a/resources/public/style.css +++ b/resources/public/style.css @@ -4,11 +4,50 @@ box-sizing: border-box } +html, body { - color: #222 + min-height: 100vh; + padding: 0; + margin: 0 +} + +body { + color: #222; + line-height: 1.2 +} + +#welcome-message { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 640px; + max-width: 100%; + padding: 48px; + + z-index: 20; + opacity: 1; + transition: opacity .2s ease; +} + +#welcome-message.hidden { + pointer-events: none; + opacity: 0; +} + +.container { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 640px; + max-width: 100%; + padding: 48px; + text-align: center; } canvas#result { + /* needs position: absolute so it's rendered above the video */ position: absolute; z-index: 10; } diff --git a/src/heyarne/all_my_friends/core.cljs b/src/heyarne/all_my_friends/core.cljs index 3a762f3..c7e9c0c 100644 --- a/src/heyarne/all_my_friends/core.cljs +++ b/src/heyarne/all_my_friends/core.cljs @@ -1,27 +1,24 @@ (ns heyarne.all-my-friends.core (:require [applied-science.js-interop :as j] - [reagent.core :as r] [reagent.dom :as dom] [heyarne.all-my-friends.views :as views])) -(defonce state (r/atom {:status :welcome-message})) - -(defn draw-results [ctx predictions] +(defn draw-results [ctx _video predictions] ;; remove previous results (.clearRect ctx 0 0 (.. ctx -canvas -width) (.. ctx -canvas -height)) ;; draw and append new results (set! (.-strokeStyle ctx) "pink") - (doseq [prediction predictions] - (doseq [[x y _] (j/get prediction :scaledMesh)] - (.beginPath ctx) - (.arc ctx x y 1 0 (* 2 Math/PI)) - (.stroke ctx)))) + (doseq [prediction predictions + [x y _] (j/get prediction :scaledMesh)] + (doto ctx + (.beginPath) + (.arc x y 1 0 (* 2 Math/PI)) + (.stroke)))) (defn ^:dev/after-load init [] (println "Initializing…") - (dom/render [views/app {:state state - :on-faces-detected draw-results}] + (dom/render [views/app {:on-faces-detected draw-results}] (.querySelector js/document "#app"))) (defonce initialize (init)) diff --git a/src/heyarne/all_my_friends/facemesh.cljs b/src/heyarne/all_my_friends/facemesh.cljs index e2cf90a..0b776d3 100644 --- a/src/heyarne/all_my_friends/facemesh.cljs +++ b/src/heyarne/all_my_friends/facemesh.cljs @@ -37,7 +37,7 @@ (defn detect-faces [model video on-faces-detected] (-> (.estimateFaces model video) (.then (fn [predictions] - (on-faces-detected predictions)))) + (on-faces-detected video predictions)))) (js/requestAnimationFrame #(detect-faces model video on-faces-detected))) (defn webcam-facemesh [{:keys [on-webcam-rejected diff --git a/src/heyarne/all_my_friends/views.cljs b/src/heyarne/all_my_friends/views.cljs index b5b516e..8769269 100644 --- a/src/heyarne/all_my_friends/views.cljs +++ b/src/heyarne/all_my_friends/views.cljs @@ -3,19 +3,53 @@ [reagent.dom :as dom] [heyarne.all-my-friends.facemesh :refer [webcam-facemesh]])) +;; minimalistic re-frame-like event handling + +(defonce state (r/atom {:status :welcome-message})) + +(def events + {:welcome/continue (fn [db _] + (assoc db :status :running)) + :running/capture (fn [db _] + (assoc db :current-capture {:img nil + :predictions nil}))}) + +(defn dispatch [[event data]] + (when-let [handler (events event)] + (js/requestAnimationFrame #(swap! state handler data)))) + +;; views + (defn welcome-message [{:keys [hidden?]}] - [:section.welcome-message - {:hidden false} + [:section#welcome-message + {:class (str (when hidden? "hidden"))} [:h1 "Hi Freund!"] [:p "Ich möchte dir kurz erklären, was dich hier erwartet: Seit der globalen Covid19-Pandemie sind wir alle dazu gezwungen, auf physischen Kontakt weitgehend zu verzichten. Ein Großteil der Zeit, die ich mit euch verbringe, hat sich ins Digitale verlagert."] [:p "Das fühlt sich sicher bald komplett normal an -- vorher möchte ich aber gerne irgendwas mit dem komischen Gefühl machen, das das hinterlässt."] [:p "Ich würde mich freuen, wenn du mir dabei hilfst. Folge dazu einfach den Anweisungen. Das Ergebnis wird hoffentlich eine schöne Sammlung von Webcambildern und 3D-Modellen eurer Köpfe" [:sup "1"] "."] - [:button "Weiter"]]) + [:button {:on-click #(dispatch [:welcome/continue])} "Weiter"]]) -(defn app [{:keys [state on-faces-detected]}] - (let [status (:status @state) - viewing-welcome-message? (= :welcome-message status)] - [:div#app - [welcome-message {:hidden? viewing-welcome-message?}] - [webcam-facemesh {:on-faces-detected on-faces-detected}]])) +(defn running [{on-faces-detected :on-faces-detected}] + (let [result (atom {:video nil + :predictions nil})] + (fn [] + [:div.container + [:p "Tippe auf den Button um mir das untere Bild zu schicken."] + [webcam-facemesh {:on-faces-detected (fn [ctx video predictions] + (swap! result assoc + :video video + :predictions predictions) + (on-faces-detected ctx video predictions))}] + [:button {:on-click #(dispatch [:running/capture @result])} "Tip"]]))) + +(defn app [{:keys [on-faces-detected]}] + (let [status (:status @state)] + [:<> + [welcome-message {:hidden? (not= :welcome-message status)}] + (case status + :permission-rejected [:div "Sad :("] + :running [running {:on-faces-detected on-faces-detected}] + + ;; default + nil)]))