Add some text, start with styling, and add minimalistic event handler
This commit is contained in:
parent
6bfa94a2ca
commit
0eed1b412b
6 changed files with 939 additions and 25 deletions
846
report.html
Normal file
846
report.html
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -7,8 +7,6 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- <canvas id="result"></canvas>
|
|
||||||
<video id="capture" playsinline></video> -->
|
|
||||||
</body>
|
</body>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,50 @@
|
||||||
box-sizing: border-box
|
box-sizing: border-box
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
body {
|
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 {
|
canvas#result {
|
||||||
|
/* needs position: absolute so it's rendered above the video */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,24 @@
|
||||||
(ns heyarne.all-my-friends.core
|
(ns heyarne.all-my-friends.core
|
||||||
(:require [applied-science.js-interop :as j]
|
(:require [applied-science.js-interop :as j]
|
||||||
[reagent.core :as r]
|
|
||||||
[reagent.dom :as dom]
|
[reagent.dom :as dom]
|
||||||
[heyarne.all-my-friends.views :as views]))
|
[heyarne.all-my-friends.views :as views]))
|
||||||
|
|
||||||
(defonce state (r/atom {:status :welcome-message}))
|
(defn draw-results [ctx _video predictions]
|
||||||
|
|
||||||
(defn draw-results [ctx predictions]
|
|
||||||
;; remove previous results
|
;; remove previous results
|
||||||
(.clearRect ctx 0 0 (.. ctx -canvas -width) (.. ctx -canvas -height))
|
(.clearRect ctx 0 0 (.. ctx -canvas -width) (.. ctx -canvas -height))
|
||||||
|
|
||||||
;; draw and append new results
|
;; draw and append new results
|
||||||
(set! (.-strokeStyle ctx) "pink")
|
(set! (.-strokeStyle ctx) "pink")
|
||||||
(doseq [prediction predictions]
|
(doseq [prediction predictions
|
||||||
(doseq [[x y _] (j/get prediction :scaledMesh)]
|
[x y _] (j/get prediction :scaledMesh)]
|
||||||
(.beginPath ctx)
|
(doto ctx
|
||||||
(.arc ctx x y 1 0 (* 2 Math/PI))
|
(.beginPath)
|
||||||
(.stroke ctx))))
|
(.arc x y 1 0 (* 2 Math/PI))
|
||||||
|
(.stroke))))
|
||||||
|
|
||||||
(defn ^:dev/after-load init []
|
(defn ^:dev/after-load init []
|
||||||
(println "Initializing…")
|
(println "Initializing…")
|
||||||
(dom/render [views/app {:state state
|
(dom/render [views/app {:on-faces-detected draw-results}]
|
||||||
:on-faces-detected draw-results}]
|
|
||||||
(.querySelector js/document "#app")))
|
(.querySelector js/document "#app")))
|
||||||
|
|
||||||
(defonce initialize (init))
|
(defonce initialize (init))
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
(defn detect-faces [model video on-faces-detected]
|
(defn detect-faces [model video on-faces-detected]
|
||||||
(-> (.estimateFaces model video)
|
(-> (.estimateFaces model video)
|
||||||
(.then (fn [predictions]
|
(.then (fn [predictions]
|
||||||
(on-faces-detected predictions))))
|
(on-faces-detected video predictions))))
|
||||||
(js/requestAnimationFrame #(detect-faces model video on-faces-detected)))
|
(js/requestAnimationFrame #(detect-faces model video on-faces-detected)))
|
||||||
|
|
||||||
(defn webcam-facemesh [{:keys [on-webcam-rejected
|
(defn webcam-facemesh [{:keys [on-webcam-rejected
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,53 @@
|
||||||
[reagent.dom :as dom]
|
[reagent.dom :as dom]
|
||||||
[heyarne.all-my-friends.facemesh :refer [webcam-facemesh]]))
|
[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?]}]
|
(defn welcome-message [{:keys [hidden?]}]
|
||||||
[:section.welcome-message
|
[:section#welcome-message
|
||||||
{:hidden false}
|
{:class (str (when hidden? "hidden"))}
|
||||||
[:h1 "Hi Freund!"]
|
[:h1 "Hi Freund!"]
|
||||||
[:p "Ich möchte dir kurz erklären, was dich hier erwartet:
|
[: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."]
|
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 "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"] "."]
|
[: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]}]
|
(defn running [{on-faces-detected :on-faces-detected}]
|
||||||
(let [status (:status @state)
|
(let [result (atom {:video nil
|
||||||
viewing-welcome-message? (= :welcome-message status)]
|
:predictions nil})]
|
||||||
[:div#app
|
(fn []
|
||||||
[welcome-message {:hidden? viewing-welcome-message?}]
|
[:div.container
|
||||||
[webcam-facemesh {:on-faces-detected on-faces-detected}]]))
|
[: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)]))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue