How to draw on a canvas with Klipse and core.async
source link: https://blog.klipse.tech/clojure/2020/09/09/core-async-canvas.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
The cool thing with Klipse is that it is 100% client-side.
It means that you can interact freely with the page where the Klipse snippets are hosted. As an example, you can draw on a canvas. All you need to do is to add in your html a <canvas>
element and refer it from your Klipse snippet.
Boring fillRect
Let’s start with a simple fillRect
manipulation:
xxxxxxxxxx
(let [canvas (js/document.getElementById "canvas-1")
ctx (.getContext canvas "2d")
width (.-width canvas)
height (.-height canvas)]
(set! (.-fillStyle ctx) "red")
(.clearRect ctx 0 0 width height)
(.fillRect ctx 0 0 width height))
the evaluation will appear here (soon)...
Random color
xxxxxxxxxx
(let [canvas (js/document.getElementById "canvas-2")
ctx (.getContext canvas "2d")
width (.-width canvas)
height (.-height canvas)
colors ["red" "blue" "green" "yellow" "magenta" "purple" "pink"]]
(set! (.-fillStyle ctx) (rand-nth colors))
(.clearRect ctx 0 0 width height)
(.fillRect ctx 0 0 width height))
xxxxxxxxxx
the evaluation will appear here (soon)...
Each time you press Ctrl-Enter
inside the snippet, the color is randomly picked.
Wouldn’t it be cool to evaluate the snippet automatically every second or so?
Random color in a loop
Let’s run the same Klipse snippet in a loop - by setting data-loop-msec="1000"
attribute of the DOM element that contains the snippet (look at the page source!):
xxxxxxxxxx
(let [canvas (js/document.getElementById "canvas-3")
ctx (.getContext canvas "2d")
width (.-width canvas)
height (.-height canvas)
colors ["red" "blue" "green" "yellow" "magenta" "purple" "pink"]]
(set! (.-fillStyle ctx) (rand-nth colors))
(.clearRect ctx 0 0 width height)
(.fillRect ctx 0 0 width height))
xxxxxxxxxx
the evaluation will appear here (soon)...
Core.async
With core.async
you can do really cool stuff - like having a progress bar:
First, let’s require core.async
(It takes a bit of time…):
xxxxxxxxxx
(ns my.canvas
(:require [cljs.core.async :refer [go go-loop <! timeout]]))
xxxxxxxxxx
the evaluation will appear here (soon)...
xxxxxxxxxx
(let [canvas (js/document.getElementById "canvas-4")
ctx (.getContext canvas "2d")
width (.-width canvas)
height (.-height canvas)]
(.clearRect ctx 0 0 width height)
(set! (.-fillStyle ctx) "green")
(go-loop [percentage 0]
(when (<= percentage 100)
(<! (timeout 200))
(.fillRect ctx 0 (/ height 2) (/ (* width percentage) 100) 10)
(recur (+ percentage 10)))))
xxxxxxxxxx
the evaluation will appear here (soon)...
It’s a bit tricky to use core.async
inside Klipse because once a snippet is evaluated it runs forever. That might cause a lot of confusion if several versions of the snippet run in parallel.
In our core.async
snippet, we have set data-eval-idle-msec="10000000"
which means that the snippets will run automatically only after 10000 seconds of idleness or when you press Ctrl-Enter
.
That’s it! Enjoy your interactive drawings…
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK