Slinky

canvasanimation

A slinky - move the cursor over the grey area and the slinky will follow. Based on _Jean-no_'s http://openprocessing.org/sketch/173277

5 Dec 2014 by rm-hull
rm-hull/7b014de283e2c2457234
slinky.cljs
(ns enchilada.slinky
  (:require
    [jayq.core :refer [show css]]
    [enchilada :refer [ctx canvas canvas-size]]
    [big-bang.core :refer [big-bang]]
    [big-bang.events.browser :refer [offset-coords]]
    [monet.canvas :refer [stroke-style stroke fill-style fill fill-rect arc begin-path close-path]]))

(def screen-area
  (let [[w h] (canvas-size)]
    {:x 0 :y 0 :w w :h h}))

(defn easing [src dest]
  (+ src (* (- dest src) 0.7)))

(def initial-state {
  :mouse {:x 400 :y 300}
  :circles (repeat 180 {:x 400 :y 300 :r 15 :start-angle 0 :end-angle (* 2 Math/PI) :counter-clockwise? true})})

(defn update-coords [event world-state]
  (assoc world-state :mouse (zipmap [:x :y] (offset-coords event))))

(defn update-state [event {:keys [mouse circles] :as world-state}]
  (loop [coords mouse
         in     circles
         out    []]
    (if (empty? in)
      (assoc world-state :circles out)
      (let [shape  (->
                     (first in)
                     (update-in [:x] easing (:x coords))
                     (update-in [:y] easing (:y coords)))]
        (recur
          shape
          (next in)
          (conj out shape))))))

(defn render [{:keys [circles]}]
  (->
    ctx
    (fill-style :lightgrey)
    (fill-rect screen-area)
    (fill-style :white)
    (stroke-style :black))

  (doseq [shape circles]
    (->
      ctx
      (begin-path)
      (arc shape)
      (fill)
      (stroke))))

(-> canvas (css :cursor "cell") (show))
(big-bang
  :event-target canvas
  :tick-rate 50
  :initial-state initial-state
  :on-mousemove update-coords
  :on-tick update-state
  :to-draw render)