Last active
June 22, 2021 06:45
-
-
Save saolsen/7799063 to your computer and use it in GitHub Desktop.
2d canvas drawing in clojurescript
This file contains 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 saolsen.draw-2d) | |
;; Draw stuff (and never care about ie ever) | |
;; There's obviously a ton this lib doesn't do, just adding what | |
;; I need when I need it. | |
(def request-animation-frame | |
(or js/requestAnimationFrame | |
js/webkitRequestAnimationFrame)) | |
(defn get-canvas-context-from-id | |
"Gets the drawing context from the id of the canvas element. | |
Actual context is in a map with the canvas element and some | |
other info." | |
[id] | |
(let [canvas (.getElementById js/document id)] | |
{:canvas canvas | |
:width (.-width canvas) | |
:height (.-height canvas) | |
:ctx (.getContext canvas "2d")})) | |
(defn to-color [& rgbas] | |
(let [csv (apply str (interpose ", " rgbas))] | |
(str "rgb(" csv ")"))) | |
(defmulti draw-object :type) | |
(defmethod draw-object :rectangle [{:keys [color pos size]} ctx] | |
(let [[x y] pos | |
[w h] size] | |
(aset ctx "fillStyle" (apply to-color color)) | |
(.fillRect ctx x y w h))) | |
(def twopi (* 2 (.-PI js/Math))) | |
(defmethod draw-object :circle [{:keys [color pos size]} ctx] | |
(let [[x y] pos] | |
(aset ctx "fillStyle" (apply to-color color)) | |
(.beginPath ctx) | |
(.arc ctx x y size 0 twopi) | |
(.closePath ctx) | |
(.fill ctx))) | |
(defmethod draw-object :line [{:keys [color width posns]} ctx] | |
(let [[startx starty] (first posns)] | |
(.beginPath ctx) | |
(.moveTo ctx startx starty) | |
(doseq [[x y] (rest posns)] | |
(.lineTo ctx x y)) | |
(.closePath ctx) | |
(aset ctx "lineWidth" width) | |
(.stroke ctx))) | |
(defn clear-canvas | |
"Clears the canvas" | |
[ctx width height] | |
(.save ctx) | |
(.setTransform ctx 1 0 0 1 0 0) | |
(.clearRect ctx 0 0 width height) | |
(.restore ctx)) | |
(defn draw-scene | |
"Draws a sequence of objects to the screen. | |
Object must contain various keys depending on their type. | |
{:type :rectangle :color [r g b a] :pos [x y] :size [w h]} | |
{:type :circle :color [r g b a] :pos [x y] :size r} | |
{:type :line :color [r g b a] :posns [x y ...]} | |
Objects are drawn in the order received and the pos coordinate | |
specifies the upper left corner." | |
[objs {:keys [width height ctx]}] | |
(clear-canvas ctx width height) | |
;; clear screen first? | |
(doseq [obj objs] | |
(draw-object obj ctx))) | |
(comment | |
(def context (get-canvas-context-from-id "draw")) | |
(print context) | |
(draw-scene [{:type :rectangle :color [200 0 0] :pos [50 50] :size [100 20]} | |
{:type :rectangle :color [0 0 200] :pos [55 55] :size [2 10]} | |
{:type :line :color [0 200 0] :width 1 :posns [[10 10] [50 10] [10 50]]} | |
] context) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment