mirror of
https://github.com/penpot/penpot.git
synced 2025-06-13 03:41:38 +02:00
✨ Improved performance on moving and zooming
This commit is contained in:
parent
96fbc83a0a
commit
12b4951994
10 changed files with 142 additions and 64 deletions
|
@ -12,6 +12,7 @@
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[cljs.spec.alpha :as s]
|
[cljs.spec.alpha :as s]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
|
[linked.set :as lks]
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as geom]
|
[app.common.geom.shapes :as geom]
|
||||||
|
@ -133,13 +134,18 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
selrect (get-in state [:workspace-local :selrect])]
|
selrect (get-in state [:workspace-local :selrect])
|
||||||
|
is-not-blocked (fn [shape-id] (not (get-in state [:workspace-data
|
||||||
|
:pages-index page-id
|
||||||
|
:objects shape-id
|
||||||
|
:blocked] false)))]
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(rx/of (update-selrect nil))
|
(rx/of (update-selrect nil))
|
||||||
(when selrect
|
(when selrect
|
||||||
(->> (uw/ask! {:cmd :selection/query
|
(->> (uw/ask! {:cmd :selection/query
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:rect selrect})
|
:rect selrect})
|
||||||
|
(rx/map #(into lks/empty-linked-set (filter is-not-blocked) %))
|
||||||
(rx/map select-shapes))))))))
|
(rx/map select-shapes))))))))
|
||||||
|
|
||||||
(defn select-inside-group
|
(defn select-inside-group
|
||||||
|
|
|
@ -257,9 +257,11 @@
|
||||||
(rx/switch-map #(snap/closest-snap-move page-id shapes objects layout %))
|
(rx/switch-map #(snap/closest-snap-move page-id shapes objects layout %))
|
||||||
(rx/map #(gpt/round % 0))
|
(rx/map #(gpt/round % 0))
|
||||||
(rx/map gmt/translate-matrix)
|
(rx/map gmt/translate-matrix)
|
||||||
(rx/map #(set-modifiers ids {:displacement %})))
|
(rx/map #(fn [state] (assoc-in state [:workspace-local :modifiers] {:displacement %}))))
|
||||||
|
|
||||||
(rx/of (apply-modifiers ids)
|
(rx/of (set-modifiers ids)
|
||||||
|
(apply-modifiers ids)
|
||||||
|
(fn [state] (update state :workspace-local dissoc :modifiers))
|
||||||
finish-transform)))))))
|
finish-transform)))))))
|
||||||
|
|
||||||
(defn- get-displacement-with-grid
|
(defn- get-displacement-with-grid
|
||||||
|
@ -339,13 +341,15 @@
|
||||||
;; -- Apply modifiers
|
;; -- Apply modifiers
|
||||||
|
|
||||||
(defn set-modifiers
|
(defn set-modifiers
|
||||||
|
([ids] (set-modifiers ids nil true))
|
||||||
([ids modifiers] (set-modifiers ids modifiers true))
|
([ids modifiers] (set-modifiers ids modifiers true))
|
||||||
([ids modifiers recurse-frames?]
|
([ids modifiers recurse-frames?]
|
||||||
(us/verify (s/coll-of uuid?) ids)
|
(us/verify (s/coll-of uuid?) ids)
|
||||||
(ptk/reify ::set-modifiers
|
(ptk/reify ::set-modifiers
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [page-id (:current-page-id state)
|
(let [modifiers (or modifiers (get-in state [:workspace-local :modifiers] {}))
|
||||||
|
page-id (:current-page-id state)
|
||||||
objects (dwc/lookup-page-objects state page-id)
|
objects (dwc/lookup-page-objects state page-id)
|
||||||
|
|
||||||
not-frame-id?
|
not-frame-id?
|
||||||
|
|
|
@ -49,6 +49,10 @@
|
||||||
(def selected-shapes
|
(def selected-shapes
|
||||||
(l/derived :selected workspace-local))
|
(l/derived :selected workspace-local))
|
||||||
|
|
||||||
|
(defn make-selected-ref
|
||||||
|
[id]
|
||||||
|
(l/derived #(contains? % id) selected-shapes))
|
||||||
|
|
||||||
(def selected-zoom
|
(def selected-zoom
|
||||||
(l/derived :zoom workspace-local))
|
(l/derived :zoom workspace-local))
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"A workspace specific shapes wrappers."
|
"A workspace specific shapes wrappers."
|
||||||
(:require
|
(:require
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
|
[okulary.core :as l]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[app.main.streams :as ms]
|
[app.main.streams :as ms]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
[app.main.ui.shapes.image :as image]
|
[app.main.ui.shapes.image :as image]
|
||||||
[app.main.data.workspace.selection :as dws]
|
[app.main.data.workspace.selection :as dws]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
[app.main.refs :as refs]
|
||||||
|
|
||||||
;; Shapes that has some peculiarities are defined in its own
|
;; Shapes that has some peculiarities are defined in its own
|
||||||
;; namespace under app.ui.workspace.shapes.* prefix, all the
|
;; namespace under app.ui.workspace.shapes.* prefix, all the
|
||||||
|
@ -68,18 +70,30 @@
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dws/change-hover-state id false)))))
|
(st/emit! (dws/change-hover-state id false)))))
|
||||||
|
|
||||||
|
(defn make-is-moving-ref
|
||||||
|
[id]
|
||||||
|
(let [check-moving (fn [local]
|
||||||
|
(and (= :move (:transform local))
|
||||||
|
(contains? (:selected local) id)))]
|
||||||
|
(l/derived check-moving refs/workspace-local)))
|
||||||
|
|
||||||
(mf/defc shape-wrapper
|
(mf/defc shape-wrapper
|
||||||
{::mf/wrap [#(mf/memo' % shape-wrapper-memo-equals?)]
|
{::mf/wrap [#(mf/memo' % shape-wrapper-memo-equals?)]
|
||||||
::mf/wrap-props false}
|
::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [shape (unchecked-get props "shape")
|
(let [shape (unchecked-get props "shape")
|
||||||
frame (unchecked-get props "frame")
|
frame (unchecked-get props "frame")
|
||||||
|
ghost? (unchecked-get props "ghost?")
|
||||||
shape (geom/transform-shape frame shape)
|
shape (geom/transform-shape frame shape)
|
||||||
opts #js {:shape shape
|
opts #js {:shape shape
|
||||||
:frame frame}
|
:frame frame}
|
||||||
alt? (mf/use-state false)
|
alt? (mf/use-state false)
|
||||||
on-mouse-enter (use-mouse-enter shape)
|
on-mouse-enter (use-mouse-enter shape)
|
||||||
on-mouse-leave (use-mouse-leave shape)]
|
on-mouse-leave (use-mouse-leave shape)
|
||||||
|
|
||||||
|
moving-iref (mf/use-memo (mf/deps (:id shape))
|
||||||
|
#(make-is-moving-ref (:id shape)))
|
||||||
|
moving? (mf/deref moving-iref)]
|
||||||
|
|
||||||
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
||||||
|
|
||||||
|
@ -88,7 +102,9 @@
|
||||||
(fn []
|
(fn []
|
||||||
(on-mouse-leave))))
|
(on-mouse-leave))))
|
||||||
|
|
||||||
(when (and shape (not (:hidden shape)))
|
(when (and shape
|
||||||
|
(or ghost? (not moving?))
|
||||||
|
(not (:hidden shape)))
|
||||||
[:g.shape-wrapper {:on-mouse-enter on-mouse-enter
|
[:g.shape-wrapper {:on-mouse-enter on-mouse-enter
|
||||||
:on-mouse-leave on-mouse-leave
|
:on-mouse-leave on-mouse-leave
|
||||||
:style {:cursor (if @alt? cur/duplicate nil)}}
|
:style {:cursor (if @alt? cur/duplicate nil)}}
|
||||||
|
|
|
@ -45,9 +45,30 @@
|
||||||
(recur (first ids) (rest ids))
|
(recur (first ids) (rest ids))
|
||||||
false))))))
|
false))))))
|
||||||
|
|
||||||
(defn make-selected-ref
|
(mf/defc frame-title
|
||||||
[id]
|
[{:keys [frame on-double-click on-mouse-over on-mouse-out]}]
|
||||||
(l/derived #(contains? % id) refs/selected-shapes))
|
(let [zoom (mf/deref refs/selected-zoom)
|
||||||
|
inv-zoom (/ 1 zoom)
|
||||||
|
{:keys [width x y]} frame
|
||||||
|
label-pos (gpt/point x (- y (/ 10 zoom)))]
|
||||||
|
[:text {:x 0
|
||||||
|
:y 0
|
||||||
|
:width width
|
||||||
|
:height 20
|
||||||
|
:class "workspace-frame-label"
|
||||||
|
;; Ensure that the label has always the same font
|
||||||
|
;; size, regardless of zoom
|
||||||
|
;; https://css-tricks.com/transforms-on-svg-elements/
|
||||||
|
:transform (str
|
||||||
|
"scale(" inv-zoom ", " inv-zoom ") "
|
||||||
|
"translate(" (* zoom (:x label-pos)) ", "
|
||||||
|
(* zoom (:y label-pos))
|
||||||
|
")")
|
||||||
|
;; User may also select the frame with single click in the label
|
||||||
|
:on-click on-double-click
|
||||||
|
:on-mouse-over on-mouse-over
|
||||||
|
:on-mouse-out on-mouse-out}
|
||||||
|
(:name frame)]))
|
||||||
|
|
||||||
(defn frame-wrapper-factory
|
(defn frame-wrapper-factory
|
||||||
[shape-wrapper]
|
[shape-wrapper]
|
||||||
|
@ -61,9 +82,8 @@
|
||||||
objects (unchecked-get props "objects")
|
objects (unchecked-get props "objects")
|
||||||
|
|
||||||
selected-iref (mf/use-memo (mf/deps (:id shape))
|
selected-iref (mf/use-memo (mf/deps (:id shape))
|
||||||
#(make-selected-ref (:id shape)))
|
#(refs/make-selected-ref (:id shape)))
|
||||||
selected? (mf/deref selected-iref)
|
selected? (mf/deref selected-iref)
|
||||||
zoom (mf/deref refs/selected-zoom)
|
|
||||||
|
|
||||||
on-mouse-down (mf/use-callback (mf/deps shape)
|
on-mouse-down (mf/use-callback (mf/deps shape)
|
||||||
#(common/on-mouse-down % shape))
|
#(common/on-mouse-down % shape))
|
||||||
|
@ -71,14 +91,9 @@
|
||||||
#(common/on-context-menu % shape))
|
#(common/on-context-menu % shape))
|
||||||
|
|
||||||
shape (geom/transform-shape shape)
|
shape (geom/transform-shape shape)
|
||||||
{:keys [x y width height]} shape
|
|
||||||
|
|
||||||
inv-zoom (/ 1 zoom)
|
|
||||||
children (mapv #(get objects %) (:shapes shape))
|
children (mapv #(get objects %) (:shapes shape))
|
||||||
ds-modifier (get-in shape [:modifiers :displacement])
|
ds-modifier (get-in shape [:modifiers :displacement])
|
||||||
|
|
||||||
label-pos (gpt/point x (- y (/ 10 zoom)))
|
|
||||||
|
|
||||||
on-double-click
|
on-double-click
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps (:id shape))
|
(mf/deps (:id shape))
|
||||||
|
@ -106,24 +121,11 @@
|
||||||
:on-context-menu on-context-menu
|
:on-context-menu on-context-menu
|
||||||
:on-double-click on-double-click
|
:on-double-click on-double-click
|
||||||
:on-mouse-down on-mouse-down}
|
:on-mouse-down on-mouse-down}
|
||||||
[:text {:x 0
|
|
||||||
:y 0
|
[:& frame-title {:frame shape
|
||||||
:width width
|
:on-context-menu on-context-menu
|
||||||
:height 20
|
:on-double-click on-double-click
|
||||||
:class "workspace-frame-label"
|
:on-mouse-down on-mouse-down}]
|
||||||
;; Ensure that the label has always the same font
|
|
||||||
;; size, regardless of zoom
|
|
||||||
;; https://css-tricks.com/transforms-on-svg-elements/
|
|
||||||
:transform (str
|
|
||||||
"scale(" inv-zoom ", " inv-zoom ") "
|
|
||||||
"translate(" (* zoom (:x label-pos)) ", "
|
|
||||||
(* zoom (:y label-pos))
|
|
||||||
")")
|
|
||||||
;; User may also select the frame with single click in the label
|
|
||||||
:on-click on-double-click
|
|
||||||
:on-mouse-over on-mouse-over
|
|
||||||
:on-mouse-out on-mouse-out}
|
|
||||||
(:name shape)]
|
|
||||||
[:g.frame {:filter (filters/filter-str filter-id shape)}
|
[:g.frame {:filter (filters/filter-str filter-id shape)}
|
||||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||||
[:& frame-shape
|
[:& frame-shape
|
||||||
|
|
|
@ -58,13 +58,15 @@
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [{:keys [id x1 y1 content group grow-type width height ] :as shape} (unchecked-get props "shape")
|
(let [{:keys [id x1 y1 content group grow-type width height ] :as shape} (unchecked-get props "shape")
|
||||||
|
selected-iref (mf/use-memo (mf/deps (:id shape))
|
||||||
selected (mf/deref refs/selected-shapes)
|
#(refs/make-selected-ref (:id shape)))
|
||||||
|
selected? (mf/deref selected-iref)
|
||||||
edition (mf/deref refs/selected-edition)
|
edition (mf/deref refs/selected-edition)
|
||||||
zoom (mf/deref refs/selected-zoom)
|
current-transform (mf/deref refs/current-transform)
|
||||||
|
|
||||||
|
render-editor (mf/use-state false)
|
||||||
|
|
||||||
edition? (= edition id)
|
edition? (= edition id)
|
||||||
selected? (and (contains? selected id)
|
|
||||||
(= (count selected) 1))
|
|
||||||
|
|
||||||
embed-resources? (mf/use-ctx muc/embed-ctx)
|
embed-resources? (mf/use-ctx muc/embed-ctx)
|
||||||
|
|
||||||
|
@ -80,23 +82,30 @@
|
||||||
|
|
||||||
filter-id (mf/use-memo filters/get-filter-id)]
|
filter-id (mf/use-memo filters/get-filter-id)]
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps shape edition selected? current-transform)
|
||||||
|
(fn [] (let [check? (and (#{:auto-width :auto-height} (:grow-type shape))
|
||||||
|
selected?
|
||||||
|
(not edition?)
|
||||||
|
(not embed-resources?)
|
||||||
|
(nil? current-transform))]
|
||||||
|
(timers/schedule #(reset! render-editor check?)))))
|
||||||
|
|
||||||
[:g.shape {:on-double-click on-double-click
|
[:g.shape {:on-double-click on-double-click
|
||||||
:on-mouse-down on-mouse-down
|
:on-mouse-down on-mouse-down
|
||||||
:on-context-menu on-context-menu
|
:on-context-menu on-context-menu
|
||||||
:filter (filters/filter-str filter-id shape)}
|
:filter (filters/filter-str filter-id shape)}
|
||||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||||
[:*
|
[:*
|
||||||
(when (and (not edition?) (not embed-resources?))
|
(when @render-editor
|
||||||
[:g {:opacity 0
|
[:g {:opacity 0
|
||||||
:style {:pointer-events "none"}}
|
:style {:pointer-events "none"}}
|
||||||
;; We only render the component for its side-effect
|
;; We only render the component for its side-effect
|
||||||
[:& text-shape-edit {:shape shape
|
[:& text-shape-edit {:shape shape
|
||||||
:zoom zoom
|
|
||||||
:read-only? true}]])
|
:read-only? true}]])
|
||||||
|
|
||||||
(if edition?
|
(if edition?
|
||||||
[:& text-shape-edit {:shape shape
|
[:& text-shape-edit {:shape shape}]
|
||||||
:zoom zoom}]
|
|
||||||
[:& text/text-shape {:shape shape
|
[:& text/text-shape {:shape shape
|
||||||
:selected? selected?}])]]))
|
:selected? selected?}])]]))
|
||||||
|
|
||||||
|
@ -277,9 +286,9 @@
|
||||||
|
|
||||||
(mf/defc text-shape-edit
|
(mf/defc text-shape-edit
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [shape zoom read-only?] :or {read-only? false} :as props}]
|
[{:keys [shape read-only?] :or {read-only? false} :as props}]
|
||||||
(let [{:keys [id x y width height content grow-type]} shape
|
(let [{:keys [id x y width height content grow-type]} shape
|
||||||
|
zoom (mf/deref refs/selected-zoom)
|
||||||
state (mf/use-state #(parse-content content))
|
state (mf/use-state #(parse-content content))
|
||||||
editor (mf/use-memo #(dwt/create-editor))
|
editor (mf/use-memo #(dwt/create-editor))
|
||||||
self-ref (mf/use-ref)
|
self-ref (mf/use-ref)
|
||||||
|
|
|
@ -186,9 +186,9 @@
|
||||||
:name (:name item)})]
|
:name (:name item)})]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps selected?)
|
(mf/deps selected)
|
||||||
(fn []
|
(fn []
|
||||||
(when selected?
|
(when (and (= (count selected) 1) selected?)
|
||||||
(.scrollIntoView (mf/ref-val dref) false))))
|
(.scrollIntoView (mf/ref-val dref) false))))
|
||||||
|
|
||||||
[:li {:on-context-menu on-context-menu
|
[:li {:on-context-menu on-context-menu
|
||||||
|
|
|
@ -247,12 +247,16 @@
|
||||||
transform (unchecked-get props "transform")
|
transform (unchecked-get props "transform")
|
||||||
selected-shapes (mf/deref (refs/objects-by-id selected))
|
selected-shapes (mf/deref (refs/objects-by-id selected))
|
||||||
frame-id (-> selected-shapes first :frame-id)
|
frame-id (-> selected-shapes first :frame-id)
|
||||||
frame (mf/deref (refs/object-by-id frame-id))]
|
frame (mf/deref (refs/object-by-id frame-id))
|
||||||
|
local (mf/deref refs/workspace-local)
|
||||||
|
|
||||||
|
update-shape (fn [shape] (-> shape
|
||||||
|
(update :modifiers merge (:modifiers local))
|
||||||
|
gsh/transform-shape))]
|
||||||
(when (and (contains? layout :dynamic-alignment)
|
(when (and (contains? layout :dynamic-alignment)
|
||||||
(= transform :move)
|
(= transform :move)
|
||||||
(not (empty? selected)))
|
(not (empty? selected)))
|
||||||
(let [shapes (map gsh/transform-shape selected-shapes)
|
(let [selrect (->> selected-shapes (map update-shape) gsh/selection-rect)
|
||||||
selrect (gsh/selection-rect shapes)
|
|
||||||
key (->> selected (map str) (str/join "-"))]
|
key (->> selected (map str) (str/join "-"))]
|
||||||
[:g.distance
|
[:g.distance
|
||||||
[:& shape-distance
|
[:& shape-distance
|
||||||
|
|
|
@ -56,11 +56,15 @@
|
||||||
:opacity line-opacity}])
|
:opacity line-opacity}])
|
||||||
|
|
||||||
(defn get-snap
|
(defn get-snap
|
||||||
[coord {:keys [shapes page-id filter-shapes]}]
|
[coord {:keys [shapes page-id filter-shapes local]}]
|
||||||
(let [shape (if (> (count shapes) 1)
|
(let [shape (if (> (count shapes) 1)
|
||||||
(->> shapes (map gsh/transform-shape) gsh/selection-rect)
|
(->> shapes (map gsh/transform-shape) gsh/selection-rect)
|
||||||
(->> shapes (first)))
|
(->> shapes (first)))
|
||||||
|
|
||||||
|
shape (if (:modifiers local)
|
||||||
|
(-> shape (assoc :modifiers (:modifiers local)) gsh/transform-shape)
|
||||||
|
shape)
|
||||||
|
|
||||||
frame-id (snap/snap-frame-id shapes)]
|
frame-id (snap/snap-frame-id shapes)]
|
||||||
|
|
||||||
(->> (rx/of shape)
|
(->> (rx/of shape)
|
||||||
|
@ -104,7 +108,7 @@
|
||||||
(hash-map coord fixedv (flip coord) maxv)]))))
|
(hash-map coord fixedv (flip coord) maxv)]))))
|
||||||
|
|
||||||
(mf/defc snap-feedback
|
(mf/defc snap-feedback
|
||||||
[{:keys [shapes page-id filter-shapes zoom] :as props}]
|
[{:keys [shapes page-id filter-shapes zoom local] :as props}]
|
||||||
(let [state (mf/use-state [])
|
(let [state (mf/use-state [])
|
||||||
subject (mf/use-memo #(rx/subject))
|
subject (mf/use-memo #(rx/subject))
|
||||||
|
|
||||||
|
@ -129,7 +133,7 @@
|
||||||
#(rx/dispose! sub))))
|
#(rx/dispose! sub))))
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps shapes)
|
(mf/deps shapes local)
|
||||||
(fn []
|
(fn []
|
||||||
(rx/push! subject props)))
|
(rx/push! subject props)))
|
||||||
|
|
||||||
|
@ -150,7 +154,7 @@
|
||||||
|
|
||||||
(mf/defc snap-points
|
(mf/defc snap-points
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [layout zoom selected page-id drawing transform] :as props}]
|
[{:keys [layout zoom selected page-id drawing transform local] :as props}]
|
||||||
(let [shapes (mf/deref (refs/objects-by-id selected))
|
(let [shapes (mf/deref (refs/objects-by-id selected))
|
||||||
filter-shapes (mf/deref refs/selected-shapes-with-children)
|
filter-shapes (mf/deref refs/selected-shapes-with-children)
|
||||||
filter-shapes (fn [id]
|
filter-shapes (fn [id]
|
||||||
|
@ -166,5 +170,6 @@
|
||||||
[:& snap-feedback {:shapes shapes
|
[:& snap-feedback {:shapes shapes
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:filter-shapes filter-shapes
|
:filter-shapes filter-shapes
|
||||||
:zoom zoom}])))
|
:zoom zoom
|
||||||
|
:local local}])))
|
||||||
|
|
||||||
|
|
|
@ -148,26 +148,35 @@
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
::mf/wrap-props false}
|
::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [data (mf/deref refs/workspace-page)
|
(let [hover (unchecked-get props "hover")
|
||||||
hover (unchecked-get props "hover")
|
|
||||||
selected (unchecked-get props "selected")
|
selected (unchecked-get props "selected")
|
||||||
|
ids (unchecked-get props "ids")
|
||||||
|
ghost? (unchecked-get props "ghost?")
|
||||||
|
data (mf/deref refs/workspace-page)
|
||||||
objects (:objects data)
|
objects (:objects data)
|
||||||
root (get objects uuid/zero)
|
root (get objects uuid/zero)
|
||||||
shapes (->> (:shapes root)
|
shapes (->> (:shapes root)
|
||||||
(map #(get objects %)))]
|
(map #(get objects %)))
|
||||||
|
|
||||||
|
shapes (if ids
|
||||||
|
(->> ids (map #(get objects %)))
|
||||||
|
shapes)]
|
||||||
[:*
|
[:*
|
||||||
[:g.shapes
|
[:g.shapes
|
||||||
(for [item shapes]
|
(for [item shapes]
|
||||||
(if (= (:type item) :frame)
|
(if (= (:type item) :frame)
|
||||||
[:& frame-wrapper {:shape item
|
[:& frame-wrapper {:shape item
|
||||||
:key (:id item)
|
:key (:id item)
|
||||||
:objects objects}]
|
:objects objects
|
||||||
|
:ghost? ghost?}]
|
||||||
[:& shape-wrapper {:shape item
|
[:& shape-wrapper {:shape item
|
||||||
:key (:id item)}]))]
|
:key (:id item)
|
||||||
|
:ghost? ghost?}]))]
|
||||||
|
|
||||||
[:& shape-outlines {:objects objects
|
(when (not ghost?)
|
||||||
:selected selected
|
[:& shape-outlines {:objects objects
|
||||||
:hover hover}]]))
|
:selected selected
|
||||||
|
:hover hover}])]))
|
||||||
|
|
||||||
(defn format-viewbox [vbox]
|
(defn format-viewbox [vbox]
|
||||||
(str/join " " [(+ (:x vbox 0) (:left-offset vbox 0))
|
(str/join " " [(+ (:x vbox 0) (:left-offset vbox 0))
|
||||||
|
@ -286,6 +295,12 @@
|
||||||
panning
|
panning
|
||||||
picking-color?]} local
|
picking-color?]} local
|
||||||
|
|
||||||
|
selrect-orig (->> (mf/deref refs/selected-objects)
|
||||||
|
gsh/selection-rect)
|
||||||
|
selrect (-> selrect-orig
|
||||||
|
(assoc :modifiers (:modifiers local))
|
||||||
|
(gsh/transform-shape))
|
||||||
|
|
||||||
file (mf/deref refs/workspace-file)
|
file (mf/deref refs/workspace-file)
|
||||||
viewport-ref (mf/use-ref nil)
|
viewport-ref (mf/use-ref nil)
|
||||||
zoom-view-ref (mf/use-ref nil)
|
zoom-view-ref (mf/use-ref nil)
|
||||||
|
@ -610,6 +625,18 @@
|
||||||
:hover (:hover local)
|
:hover (:hover local)
|
||||||
:selected (:selected selected)}]
|
:selected (:selected selected)}]
|
||||||
|
|
||||||
|
(when (= :move (:transform local))
|
||||||
|
[:svg.ghost
|
||||||
|
{:x (:x selrect)
|
||||||
|
:y (:y selrect)
|
||||||
|
:width (:width selrect)
|
||||||
|
:height (:height selrect)
|
||||||
|
:style {:pointer-events "none"}}
|
||||||
|
|
||||||
|
[:g {:transform (str/fmt "translate(%s,%s)" (- (:x selrect-orig)) (- (:y selrect-orig)))}
|
||||||
|
[:& frames {:ids selected
|
||||||
|
:ghost? true}]]])
|
||||||
|
|
||||||
(when (seq selected)
|
(when (seq selected)
|
||||||
[:& selection-handlers {:selected selected
|
[:& selection-handlers {:selected selected
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
|
@ -628,7 +655,8 @@
|
||||||
:drawing drawing-obj
|
:drawing drawing-obj
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:selected selected}]
|
:selected selected
|
||||||
|
:local local}]
|
||||||
|
|
||||||
[:& snap-distances {:layout layout
|
[:& snap-distances {:layout layout
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue