Demo(check browser compatibility first) http://repo.tiye.me/Quamolit/quamolit/
Features:
- declarative component markups for Canvas
- animation abstractions
- persistent data by default with ClojureScript
Still prototype... Quamolit requires
ctx.addHitRegion(opts)
, which is an experimental technology.
Quamolit is trying to combine two things:
- declarative programming experience like React
- pixels manipulating and animations in HTML5 Canvas
[quamolit "0.1.6"]
Browser docs/ for a little more details.
You may require Quamolit with higher level APIs:
(quamolit.core/render-page store states-ref target)
(quamolit.core/configure-canvas target)
(quamolit.core/setup-events target dispatch)
(ns quamolit.main
(:require [quamolit.core :refer [render-page
configure-canvas
setup-events]]
[quamolit.util.time :refer [get-tick]]
[quamolit.updater.core :refer [updater-fn]]
[devtools.core :as devtools]))
(defonce store-ref (atom []))
(defonce states-ref (atom {}))
(defonce loop-ref (atom nil))
(defn dispatch [op op-data]
(let [new-tick (get-tick)
new-store (updater-fn @store-ref op op-data new-tick)]
(reset! store-ref new-store)))
(defn render-loop []
(let [target (.querySelector js/document "#app")]
(render-page @store-ref states-ref target)
(reset! loop-ref (js/requestAnimationFrame render-loop))))
(defn -main []
(let [target (.querySelector js/document "#app")]
(configure-canvas target)
(setup-events target dispatch)
(render-loop)))
(set! js/window.onload -main)
(set! js/window.onresize configure-canvas)
(defn on-jsload []
(js/cancelAnimationFrame @loop-ref)
(js/requestAnimationFrame render-loop)
(.log js/console "code updated..."))
Also you may use lower level APIs directly by copy/paste this Gist:
(defn init-state [arg1 arg2])
(defn update-state [old-state state-arg1 state-arg2])
(defn init-instant [args state at-place?])
(defn on-tick [instant tick elapsed])
(defn on-update [instant old-args args old-state state])
(defn on-unmount [instant tick])
(defn remove? [instant])
(defn render [arg1 arg2]
(fn [state mutate instant tick]))
(create-comp :demo render)
(create-comp :demo init-state update-state render)
(create-comp :demo init-instant on-tick on-update on-mount remove? render)
(create-comp :demo init-state update-state init-instant on-tick on-update on-mount remove? render)
(mutate state-arg1 state-arg2)
(dispatch op op-data)
(defn updater-fn [old-store op op-data op-id])
(quamolit.util.iterate/iterate-instant instant :x :x-velovity elapsed [lower-bound upper-bound])
(quamolit.util.iterate/tween [40 60] [0 1000] 800)
Shape records:
name
keywordprops
a hashmap of:-
style
a hashmap of styles used in Canvas API
-
event
a hashmap of events, mainly:click
events
-
attrs
a hashmap
children
sorted hashmap with values of child nodes
Component record:
name
keywordcoord
a vector of numbers(maybe also keywords and strings)args
props of components are passed in a list, not hashmapstate
any type frominit-state
instant
any type frominit-instant
, mainly hashmapsinit-state
function to initilize component stateupdate-state
function to transform component stateinit-instant
function to initilize component animation stateon-tick
function to update animation state at every tickon-update
function to update animation state on every store or states changeon-unmount
function to update animation state when component removed(not destroyed yet)remove?
function to detect if component totally removed(or destroyed)render
function to rendertree
cached from render treefading?
boolean, whether component unmounted(waiting to be destroyed)
(line {:style {
:x0 0 :y0 0 :x1 40 :y1 40
:line-width 4
:stroke-style (hsl 200 870 50)
:line-cap "round"
:line-join "round"
:milter-limit 8
}})
(arc {:style {
:x 0 :y 0:r 40
:s-angle 0
:e-angle 60
:line-width 4
:counterclockwise true
:line-cap "round"
:line-join "round"
:miter-limit 8
:fill-style nil
:stroke-style nil
}})
(rect {:style {
:w 100 :h 40
:x (- (/ w 2)) :y (- (/ h 2))
:line-width 2
}})
(text {:style {
:x 0
:y 0
:fill-style (hsl 0 0 0)
:text-align "center"
:base-linee "middle"
:size 20
:font-family "Optima"
:max-width 400
:text ""
}})
(image {:style {
:src "lotus.jpg"
:sx 0
:sy 0
:sw 40
:sh 40
:dx 0
:dy 0
:dw 40
:dh 40
}})
(translate {:style {:x 0 :y 0}})
(scale {:style {:ratio 1.2}})
(alpha {:style {:opacity 0.5}})
(rotate {:style {:angle 30}})
(button {:style {
:x 0 :y 0
:w 100 :h 40 :text "button"
:surface-color (hsl 0 80 80) :text-color (hsl 0 0 10)
:font-family "Optima"
:font-size 20}})
(input {:style {:w 0 :h 0 :text ""}})
(comp-debug data {})
To run this project:
yarn
yarn html
yarn watch # localhost:7000
MIT