mirror of
https://github.com/penpot/penpot.git
synced 2025-05-23 14:26:12 +02:00
⚡ Improve selection performance
This commit is contained in:
parent
b05908a760
commit
fb9b023fae
6 changed files with 76 additions and 36 deletions
|
@ -149,6 +149,7 @@
|
|||
(d/export gpr/points->rect)
|
||||
(d/export gpr/center->rect)
|
||||
(d/export gpr/join-rects)
|
||||
(d/export gpr/contains-selrect?)
|
||||
|
||||
(d/export gtr/move)
|
||||
(d/export gtr/absolute-move)
|
||||
|
|
|
@ -121,3 +121,11 @@
|
|||
(or (< px x2) (s= px x2))
|
||||
(or (> py y1) (s= py y1))
|
||||
(or (< py y2) (s= py y2)))))
|
||||
|
||||
(defn contains-selrect?
|
||||
"Check if a selrect sr2 is contained inside sr1"
|
||||
[sr1 sr2]
|
||||
(and (>= (:x1 sr2) (:x1 sr1))
|
||||
(<= (:x2 sr2) (:x2 sr1))
|
||||
(>= (:y1 sr2) (:y1 sr1))
|
||||
(<= (:y2 sr2) (:y2 sr1))))
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
(->> move-stream
|
||||
;; When transforming shapes we stop querying the worker
|
||||
(rx/filter #(not (some? (mf/ref-val transform-ref))))
|
||||
(rx/switch-map query-point))
|
||||
(rx/merge-map query-point))
|
||||
|
||||
(->> move-stream
|
||||
;; When transforming shapes we stop querying the worker
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
"translate(" (* zoom x) ", " (* zoom y) ")")))
|
||||
|
||||
(mf/defc frame-title
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [frame modifiers selected? zoom on-frame-enter on-frame-leave on-frame-select]}]
|
||||
(let [{:keys [width x y]} (gsh/transform-shape frame)
|
||||
label-pos (gpt/point x (- y (/ 10 zoom)))
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
(->> (:stream worker)
|
||||
(rx/filter #(= (:reply-to %) sender-id))
|
||||
(take-messages)
|
||||
(rx/filter (complement :dropped))
|
||||
(rx/map handle-response)))
|
||||
(rx/empty)))))
|
||||
|
||||
|
@ -91,9 +92,8 @@
|
|||
worker))
|
||||
|
||||
(defn- handle-response
|
||||
[{:keys [payload error dropped]}]
|
||||
(when-not dropped
|
||||
[{:keys [payload error]}]
|
||||
(if-let [{:keys [data message]} error]
|
||||
(throw (ex-info message data))
|
||||
payload)))
|
||||
payload))
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
[clojure.set :as set]
|
||||
[okulary.core :as l]))
|
||||
|
||||
(def ^:const padding-percent 0.10)
|
||||
|
||||
(defonce state (l/atom {}))
|
||||
|
||||
(defn index-shape
|
||||
|
@ -37,28 +39,47 @@
|
|||
:clip-parents clip-parents
|
||||
:parents parents)))))
|
||||
|
||||
(defn objects-bounds
|
||||
"Calculates the bounds of the quadtree given a objects map."
|
||||
[objects]
|
||||
(-> objects
|
||||
(dissoc uuid/zero)
|
||||
vals
|
||||
gsh/selection-rect))
|
||||
|
||||
(defn add-padding-bounds
|
||||
"Adds a padding to the bounds defined as a percent in the constant `padding-percent`.
|
||||
For a value of 0.1 will add a 20% width increase (2 x padding)"
|
||||
[bounds]
|
||||
(let [width-pad (* (:width bounds) padding-percent)
|
||||
height-pad (* (:height bounds) padding-percent)]
|
||||
(-> bounds
|
||||
(update :x - width-pad)
|
||||
(update :x1 - width-pad)
|
||||
(update :x2 + width-pad)
|
||||
(update :y1 - height-pad)
|
||||
(update :y2 + height-pad)
|
||||
(update :width + width-pad width-pad)
|
||||
(update :height + height-pad height-pad))))
|
||||
|
||||
(defn- create-index
|
||||
[objects]
|
||||
(let [shapes (-> objects (dissoc uuid/zero) (vals))
|
||||
(let [shapes (-> objects (dissoc uuid/zero) vals)
|
||||
parents-index (cp/generate-child-all-parents-index objects)
|
||||
clip-parents-index (cp/create-clip-index objects parents-index)
|
||||
bounds #js {:x (int -0.5e7)
|
||||
:y (int -0.5e7)
|
||||
:width (int 1e7)
|
||||
:height (int 1e7)}
|
||||
bounds (-> objects objects-bounds add-padding-bounds)
|
||||
|
||||
index (reduce (index-shape objects parents-index clip-parents-index)
|
||||
(qdt/create bounds)
|
||||
(qdt/create (clj->js bounds))
|
||||
shapes)
|
||||
|
||||
z-index (cp/calculate-z-index objects)]
|
||||
|
||||
{:index index :z-index z-index}))
|
||||
{:index index :z-index z-index :bounds bounds}))
|
||||
|
||||
(defn- update-index
|
||||
[{index :index z-index :z-index :as data} old-objects new-objects]
|
||||
|
||||
(if (some? data)
|
||||
(let [changes? (fn [id]
|
||||
(not= (get old-objects id)
|
||||
(get new-objects id)))
|
||||
|
@ -82,10 +103,7 @@
|
|||
|
||||
z-index (cp/update-z-index z-index changed-ids old-objects new-objects)]
|
||||
|
||||
{:index index :z-index z-index})
|
||||
|
||||
;; If not previous data. We need to create from scratch
|
||||
(create-index new-objects)))
|
||||
(assoc data :index index :z-index z-index)))
|
||||
|
||||
(defn- query-index
|
||||
[{index :index z-index :z-index} rect frame-id full-frame? include-frames? clip-children? reverse?]
|
||||
|
@ -154,7 +172,19 @@
|
|||
|
||||
(defmethod impl/handler :selection/update-index
|
||||
[{:keys [page-id old-objects new-objects] :as message}]
|
||||
(swap! state update page-id update-index old-objects new-objects)
|
||||
(let [update-page-index
|
||||
(fn [index]
|
||||
(let [old-bounds (:bounds index)
|
||||
new-bounds (objects-bounds new-objects)]
|
||||
|
||||
;; If the new bounds are contained within the old bounds we can
|
||||
;; update the index.
|
||||
;; Otherwise we need to re-create it
|
||||
(if (and (some? index)
|
||||
(gsh/contains-selrect? old-bounds new-bounds))
|
||||
(update-index index old-objects new-objects)
|
||||
(create-index new-objects))))]
|
||||
(swap! state update page-id update-page-index))
|
||||
nil)
|
||||
|
||||
(defmethod impl/handler :selection/query
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue