Permalink
Browse files

initial canvas stuff

Signed-off-by: Chris Granger <ibdknox@gmail.com>
  • Loading branch information...
1 parent 07436c7 commit 2d9388efa68f30be97e261194a6f5eb70a28b784 @ibdknox committed Sep 17, 2011
View
@@ -0,0 +1,101 @@
+(ns pinot.dom
+ (:require [goog.dom :as dom]
+ [goog.events :as events]
+ [goog.style :as gstyle]
+ [goog.dom.query :as query]
+ [goog.dom.forms :as forms]
+ [pinot.util.clj :as pclj]
+ [pinot.util.js :as pjs]))
+
+;; ********************************************
+;; Pinot specific
+;; ********************************************
+
+(defn pinot-group [func]
+ (when (fn? func)
+ (let [elem (func)]
+ (attr (first elem) :pinotGroup))))
+
+;; ********************************************
+;; Attribute manipulation
+;; ********************************************
+
+(defn css [elem k & [v]]
+ (cond
+ (map? k) (doseq [[prop value] k]
+ (css elem prop value))
+ (nil? v) (gstyle/getStyle elem (name k))
+ :else (doseq [el (pclj/->coll elem)]
+ (gstyle/setStyle el (name k) (name v))))
+ elem)
+
+(defn attr
+ ([elem attrs]
+ (if-not (map? attrs)
+ (. elem (getAttribute (name attrs)))
+ (do
+ (doseq [[k v] attrs]
+ (attr elem k v))
+ elem)))
+ ([elem k v]
+ (doseq [el (pclj/->coll elem)]
+ (. el (setAttribute (name k) v)))
+ elem))
+
+(defn text [elem v]
+ (doseq [el (pclj/->coll elem)]
+ (dom/setTextContent el v))
+ elem)
+
+(defn val [elem & [v]]
+ (let [elem (if (coll? elem)
+ (first elem)
+ elem)]
+ (if v
+ (do
+ (forms/setValue elem v)
+ elem)
+ (forms/getValue elem))))
+
+;; ********************************************
+;; Dom interaction functions
+;; ********************************************
+
+(defn parent [elem]
+ (.parentNode elem))
+
+(defn is-dom? [elem]
+ (dom/isNodeLike elem))
+
+(defn dom-clone [elem]
+ (. elem (cloneNode true)))
+
+;;TODO: for a collection of elements it appends the same DOM
+;; element to each one, causing it just to move around. Really
+;; if it's a collection we should clone the html element(s) and
+;; append new ones to each of the items in elem. This, however,
+;; makes it impossible to keep track of an individual dom fragment
+;; for named view objects.
+(defn append [elem html]
+ (doseq [el (pclj/->coll elem)
+ tag (pclj/->coll html)]
+ (dom/appendChild el (dom-clone tag))))
+
+(defn unappend [elem]
+ (doseq [elem (pclj/->coll elem)]
+ (dom/removeNode elem)))
+
+(defn nodelist->coll [nl]
+ ;; The results are a nodelist, which looks like an array, but
+ ;; isn't one. We have to turn it into a collection that we can
+ ;; work with.
+ (for [x (range 0 (.length nl))]
+ (aget nl x)))
+
+(defn query [q]
+ (let [q (if (fn? q)
+ (str "[pinotGroup$=" (pinot-group q) "]")
+ q)
+ results (dom/query q)]
+ (nodelist->coll results)))
+
View
@@ -0,0 +1,131 @@
+(ns pinot.draw.canvas
+ (:require [pinot.html :as html]
+ [pinot.dom :as dom]
+ [pinot.draw.core :as draw]
+ [pinot.util.js :as pjs]))
+
+;;*********************************************
+;; Canvas drawing functions
+;;*********************************************
+
+(defn get-context [canvas type]
+ (. canvas (getContext (name type))))
+
+(defn begin-path [ctx]
+ (. ctx (beginPath))
+ ctx)
+
+(defn close-path [ctx]
+ (. ctx (closePath))
+ ctx)
+
+(defn fill [ctx]
+ (. ctx (fill))
+ ctx)
+
+(defn stroke [ctx]
+ (. ctx (stroke))
+ ctx)
+
+(defn clear-rect [ctx {:keys [x y w h]}]
+ (. ctx (clearRect x y w h))
+ ctx)
+
+(defn rect [ctx {:keys [x y w h]}]
+ (begin-path ctx)
+ (. ctx (rect x y w h))
+ (close-path ctx)
+ (fill ctx)
+ ctx)
+
+(defn circle [ctx {:keys [x y r]}]
+ (begin-path ctx)
+ (. ctx (arc x y r 0 (* (.PI js/Math) 2) true))
+ (close-path ctx)
+ (fill ctx)
+ ctx)
+
+(defn text [ctx {:keys [text x y]}]
+ (. ctx (fillText text x y)))
+
+(defn fill-style [ctx color]
+ (set! ctx.fillStyle color)
+ ctx)
+
+(defn stroke-style [ctx color]
+ (set! ctx.strokeStyle color)
+ ctx)
+
+(defn stroke-width [ctx w]
+ (set! ctx.lineWidth w)
+ ctx)
+
+(defn move-to [ctx x y]
+ (. ctx (moveTo x y))
+ ctx)
+
+(defn line-to [ctx x y]
+ (. ctx (lineTo x y))
+ ctx)
+
+(defn alpha [ctx a]
+ (set! ctx.globalAlpha a)
+ ctx)
+
+(defn save [ctx]
+ (. ctx (save))
+ ctx)
+
+(defn restore [ctx]
+ (. ctx (restore))
+ ctx)
+
+;;*********************************************
+;; Canvas Entities
+;;*********************************************
+
+(def entities (atom {}))
+
+(defn add-entity [k ent]
+ (swap! entities assoc k ent))
+
+(defn remove-entity [k]
+ (swap! entities dissoc k))
+
+(defn get-entity [k]
+ (get-in @entities [k :value]))
+
+(defn update-entity [k func & extra]
+ (swap! entities (fn [ents]
+ (assoc ents k (apply func (get ents k) extra)))))
+
+(defn entity [v update draw]
+ {:value v
+ :draw draw
+ :update update})
+
+(defn update-loop []
+ (doseq[[k {:keys [update value]}] @entities]
+ (when update
+ (swap! entities assoc-in [k :value] (update value))))
+ (js/setTimeout update-loop 10))
+
+(defn draw-loop [ctx width height]
+ (clear-rect ctx {:x 0 :y 0 :w width :h height})
+
+ (doseq[[_ {:keys [draw value]}] @entities]
+ (when draw
+ (draw ctx value)))
+ (draw/animation-frame #(draw-loop ctx width height)))
+
+(defn init [canvas & [context-type]]
+ (let [ct (or context-type "2d")
+ width (dom/attr canvas :width)
+ height (dom/attr canvas :height)
+ ctx (get-context canvas ct)]
+ (update-loop)
+ (draw-loop ctx width height)))
+
+
+
+
View
@@ -0,0 +1,12 @@
+(ns pinot.draw.core)
+
+(def animation-frame
+ (or (.requestAnimationFrame js/window)
+ (.webkitRequestAnimationFrame js/window)
+ (.mozRequestAnimationFrame js/window)
+ (.oRequestAnimationFrame js/window)
+ (.msRequestAnimationFrame js/window)
+ (fn [callback] (js/setTimeout callback 17))))
+
+
+
@@ -0,0 +1,66 @@
+(ns pinot.draw.geometry)
+
+;;**************************************************
+;; Pathing functions
+;;**************************************************
+
+(defn distance [origin target]
+ (let [dx (- (:x target) (:x origin))
+ dy (- (:y target) (:y origin))
+ dir-x (if (= 0 dx)
+ dx
+ (/ dx (Math/abs dx)))
+ dir-y (if (= 0 dy)
+ dy
+ (/ dy (Math/abs dy)))
+ dist (Math/sqrt (+ (Math/pow dx 2) (Math/pow dy 2)))]
+ {:delta {:x dx :y dy}
+ :dir {:x dir-x :y dir-y}
+ :dist dist}))
+
+;;**************************************************
+;; Bounding functions
+;;**************************************************
+
+(defn bottom-right [{:keys [x y w h]}]
+ {:x (+ x (/ w 2))
+ :y (+ y (/ h 2))})
+
+(defn top-left [{:keys [x y w h]}]
+ {:x (- x (/ w 2))
+ :y (- y (/ h 2))})
+
+(defn in-radius? [origin obj radius]
+ (let [{:keys [dist]} (distance origin obj)]
+ (< dist radius)))
+
+(defn collision? [obj obj2]
+ (let [br (bottom-right obj)
+ tl (top-left obj)
+ br2 (bottom-right obj2)
+ tl2 (top-left obj2)]
+ (and
+ ;;If the tops are higher than the bottoms
+ (and (< (:y tl) (:y br2))
+ (< (:y tl2) (:y br)))
+ ;;And the lefts are "lefter" than the rights
+ (and (< (:x tl) (:x br2))
+ (< (:x tl2) (:x br))))))
+
+(defn contained? [container obj]
+ (let [cbr (bottom-right container)
+ ctl (top-left container)
+ br (bottom-right obj)
+ tl (top-left obj)]
+ (and
+ (and (< (:x ctl) (:x tl))
+ (< (:y ctl) (:y tl)))
+ (and (> (:x cbr) (:x br))
+ (> (:y cbr) (:y br))))))
+
+(defn in-bounds? [obj x2 y2]
+ (let [br (bottom-right obj)
+ tl (top-left obj)]
+ (and (< (:x tl) x2 (:x br))
+ (< (:y tl) y2 (:y br)))))
+
@@ -1,5 +1,7 @@
-(ns pinot.visual
+(ns pinot.draw.visualization
(:require [pinot.html :as html]
+ [pinot.dom :as dom]
+ [pinot.draw.core :as draw]
[pinot.util.js :as pjs]))
(defn visual [data]
@@ -17,7 +19,7 @@
(let [v (if (fn? v)
(v d idx)
v)]
- (html/attr elem k v))))
+ (dom/attr elem k v))))
(defn create-elem [elem d idx]
(cond
@@ -33,7 +35,7 @@
(method cur))))
(defn select [query]
- (html/dom-find query))
+ (dom/query query))
(defn data [vis d]
(assoc vis :data d))
@@ -42,26 +44,18 @@
{:elems elems
:dur dur})
-(def animation-frame
- (or (.requestAnimationFrame js/window)
- (.webkitRequestAnimationFrame js/window)
- (.mozRequestAnimationFrame js/window)
- (.oRequestAnimationFrame js/window)
- (.msRequestAnimationFrame js/window)
- (fn [callback] (js/setTimeout callback 17))))
-
(defn do-animation [{:keys [start-time dur tween] :as anim}]
(let [now (. js/Date (now))
elapsed (min (/ (- now start-time) dur) 1)]
(tween elapsed)
(when-not (= elapsed 1)
- (animation-frame (partial do-animation anim)))))
+ (draw/animation-frame (partial do-animation anim)))))
(defn end-states [elems attr data]
(for [[el d] (map list elems data)]
(for [[k v] attr]
(let [v (if (fn? v) (v d) v)
- init (pjs/as-int (html/attr el k))
+ init (pjs/as-int (dom/attr el k))
delta (- v init)]
[k init delta]))))
@@ -73,7 +67,7 @@
[k init delta] attrs]
(let [elapsed-delta (* elapsed-perc delta)
change (+ init elapsed-delta)]
- (html/attr el k change))))))
+ (dom/attr el k change))))))
(defn start [{:keys [dur] :as transition}]
(let [now (. js/Date (now))]
Oops, something went wrong.

0 comments on commit 2d9388e

Please sign in to comment.