Generative arts with Phlox, a cljs wrapper on Pixi.js

I created a toy project called “Phlox” which added a “virtual DOM”-like abstraction to Pixi.js . It has several basic features from Pixi.js . So I can play with Pixi.js with an experience like using React.

I have to claim that it’s mostly a toy project since I won’t really working on Phlox for long. And many features from Pixi are just not available via virtual DOM abstraction of Phlox. But I do managed to make some interesting pieces with Phlox.

Pixel Way is a very tiny game of random walks. By clicking “Run”, a dynamic map is generated. Each grid respond to mouseover events and so that it can be used to create a continuous path. When the path reaches bottom right corner and the game finishes.

The other project is just a collection of several shapes or patterns generated with Phlox. Here are examples:

Besides, Pixi.js has a very rich event system. So it’s quite simple to build a slider component which changes number with mouse dragging events:

So, it’s a toy playing with canvas but with mouse events. It’s like SVG but being faster since Pixi makes use of WebGL rendering.

Code examples

To render a simple component with Phlox, say rendering a tab button, with rect and text. Writing code like in virtual DOM frameworks, just components nested with elements:

image

(defcomp
 comp-tab
 (title tab idx selected?)
 (container
  {:position [0 (* 40 idx)]}
  (rect
   {:position [0 0],
    :size [120 32],
    :fill (hslx 200 60 (if selected? 30 14)),
    :on {:click (fn [e d!] (d! :tab tab))}})
  (text
   {:text title,
    :position [20 3],
    :style {:fill (hslx 0 0 100), :font-size 20, :font-family style/font-fancy}})))

Pixi elements are a bit different from DOM elements. Need to figure that part by yourself…

To attach events, use :on keyword, it’s followed by a map of events, click mousedown mousemove… like defined in Pixi Graphics nodes. d! is the function you call (dispatch! action data-of-action) to the global store with a pure updater function.

There’s also an :on-keyboard field with entries like :down :press :up for listening global keyboard events. It’s quite naive and slow though.

Component states

Phlox does not build component level states like React. Plus React’s component states breaks states during hot code swapping in some cases. But there’s a way to simulate states by storing states tree on global store and manage states with a cursor, well, manually

You may see code like below if you read example code, it’s maintaining states manually:

(let [state (or
              (:data states) ; existing data from states tree
              initial-state)] ; initial
  ; ...
(comp-drag-point
   (conj cursor idx) ; generates a child cursor
   (get states idx) ; branching states tree with same key
   {:position point,
    :on-change (fn [position d!]
      ; d! cursor.... special case of (dispatch! :action data) for states
      (d! cursor (assoc-in state [:points idx] position)))})

You also need an updater function handing that correctly…

Such dirty code!

Workflow

Since the library is really messy, I suggest cloning my workflow if you find my work interesting to play with. Clone the repo, rm calcit.cirru && yarn && yarn page && yarn watch to try:

Props validation

So each Phlox element takes a props in map. Take circle for example, it has some props which is a subset from Pixi Graphics nodes:

{
  :position [1 1]
  :radius 1
  :line-style {
    :width 2
    :color 0x000001
    :alpha 1
  }
  :fill 0x000001
  :on {
    :pointerdown (fn [])
  }
  :alpha 1
  :on-keyboard {
    :down (fn [])
  }
}

To make typos easier for be observed, I added some validations with Lilac, which is another project of mime for recursive data validations in runtime. (It can be accomplished with Spec but namespaced keywords are really annoying to me.)

Anyway when typo are detected, warnings appear in Console. It should be not hard to locate the component that has typo in most cases.

image

image

Other thinking…

Pixi is great! I should try adding more features to Phlox, currently there are only shape, (no filters, gradients, animations… etc.) I was really enjoying the shiny shapes generated with Phlox in the past weeks. Well, it’s very special time in China. I won’t have that much time playing like this later.

reactpixi and react-threejs-fiber might be even cooler. I’m aware of those pieces, but not tried, and again, hot code swapping issues…

2 Likes

Recorded my demos on http://repo.quamolit.org/circling-tree/

1 Like