                        (<= 1.5 t 2) (- 0.5 (- t 1.5))
                        (<= 2 t) 0)))))
 
+(defn view-radius [state pos]
+  (let [{:keys [view-size camera-pos]} state
+        view-center (scalar-multiply view-size 0.5)
+        view-radius (dist view-center)
+        displacement (subtract-vec pos camera-pos)
+        r (dist displacement)]
+    (project-radius r view-radius)))
+
 (defn sync-graph! [state]
   (let [{:keys [svg nodes]} state
-        _view-position (fn [d] (view-position state (:x d) (:y d)))
+        _view-position (fn [d] (view-position state (:pos d)))
         view-x (comp :x _view-position)
         view-y (comp :y _view-position)
-        _view-radius (fn [d] (view-radius state (:x d) (:y d)))]
+        _view-radius (fn [d] (view-radius state (:pos d)))]
     (-> svg
         (.selectAll ".node")
         (.data (apply array nodes))

          (.empty rx-observable)
          (let [{:keys [vx vy]} a]
            (.generateWithRelativeTime rx-observable
              {:dx (* update-interval-ms (or vx 0)), :dy (* update-interval-ms (or vy 0))}
              (fn [d] 
                (> (dist-sq (:dx d) (:dy d)) min-slide-speed-sq))
              (fn [d] (let [[x y] (apply dampen (map d [:dx :dy]))] {:dx x :dy y}))
              identity
              (constantly update-interval-ms))))))))

(defn move-camera-on-swipe! [manager current-state]
  (.subscribe
    (swipe-displacements-observable manager (:svg @current-state))
    (fn [d] 
      (let [{:keys [dx dy]} d] (move-camera! current-state dx dy)))))

;; Gestures - pinch



(defn node [title x y]
  {:title title
   :pos (math-vec x y)})

(defn load-nodes [json-file callback]
  (.json d3 json-file
