Created
December 7, 2013 16:42
-
-
Save DarrenN/7845047 to your computer and use it in GitHub Desktop.
Gnarly drag/drop with ClojureScript and core.async - http://cljsfiddle.net/fiddle/DarrenN.async.delta
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="canvas"> | |
<h1>Click and drag boxes</h1> | |
<ul> | |
<li class="box"></li> | |
<li class="box"></li> | |
<li class="box"></li> | |
</ul> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns DarrenN.async.delta | |
(:require [cljs.core.async :refer (<! >! chan put! take! alts! timeout close! dropping-buffer sliding-buffer)] | |
[domina :as dom] | |
[domina.events :as events] | |
[domina.css :as css]) | |
(:require-macros [cljs.core.async.macros :refer (go alt!)])) | |
(defn log [o] | |
(.log js/console o)) | |
(defn msg [s id] | |
(dom/set-text! (dom/by-id id) s)) | |
(defn merge-chans [& chans] | |
(let [rc (chan)] | |
(go | |
(loop [] | |
(put! rc (first (alts! chans))) | |
(recur))) | |
rc)) | |
(defn filter-chan [pred channel] | |
(let [rc (chan)] | |
(go (loop [] | |
(let [val (<! channel)] | |
(if (pred val) (put! rc val)) | |
(recur)) | |
)) | |
rc)) | |
(defn listen [el type msg] | |
(let [in (chan)] | |
(events/listen! (dom/by-id el) type (fn [e] (put! in [msg e]))) | |
in)) | |
(defn stop-drag [box chan] | |
(close! chan) | |
(dom/remove-class! box "drag") | |
box) | |
; this is WAY gnarly and needs a re-think | |
(defn start-drag [msg evt chan] | |
(when (dom/has-class? (:target evt) "box") | |
; make a new channel just for the drag | |
(let [box (:target evt) | |
mouse (listen "canvas" :mousemove :mouse) | |
up (listen "canvas" :mouseup :up) | |
chan (merge-chans mouse up)] | |
(dom/add-class! box "drag") | |
(go | |
(loop [b box] | |
(let [[msg-name msg-data] (<! chan)] | |
(when (= msg-name :up) | |
(stop-drag box chan)) | |
(when-not (= msg-name :up) | |
(dom/set-styles! b {:top (str (- (:clientY msg-data) 40) "px"), :left (str (- (:clientX msg-data) 40) "px")}) | |
(recur box)))))))) | |
(defn app-loop [start-state] | |
"Global loop - listen to all the things and dispatch" | |
(let [mouse (listen "canvas" :mousemove :mouse) | |
down (listen "canvas" :mousedown :down) | |
up (listen "canvas" :mouseup :up) | |
input (merge-chans mouse down up)] | |
(go | |
(loop [state start-state] | |
; Here do a condp on the msg-name and route | |
; an :up to its own function with its own go routine | |
; which handles the dragging of an object | |
(let [[msg-name msg-data] (<! input)] | |
(recur (condp = msg-name | |
:down (start-drag msg-name msg-data input) | |
:up msg-name | |
:mouse msg-name))))))) | |
(app-loop :up) ; loopin! | |
; scatter dem boxes | |
(doseq [x (dom/nodes (css/sel ".box"))] | |
(dom/set-styles! x {:top (str (.floor js/Math (+ (rand 400) 50)) "px"), :left (str (.floor js/Math (+ (rand 400) 50)) "px")})) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
p { | |
color: #f41; | |
font-family: helvetica; | |
font-size: 2em; | |
text-align: center; | |
margin-top: 60px; | |
} | |
h1 { | |
font-size: 16px; | |
color: white; | |
font-family: sans-serif; | |
padding: 20px; | |
} | |
#canvas { | |
width: 100%; | |
min-height: 500px; | |
background: red; | |
} | |
ul { | |
margin: 20px; | |
} | |
.box { | |
width: 80px; | |
height: 80px; | |
background: yellow; | |
position: absolute; | |
z-index: 100; | |
list-style-type: none; | |
display: inline-block; | |
box-shadow: 0px 0px 3px maroon; | |
} | |
.drag { | |
z-index: 200; | |
background: green; | |
position: absolute; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment