Performance improvements on selection handlers.

This commit is contained in:
Andrey Antukh 2020-05-01 11:07:39 +02:00
parent a5592dfe04
commit 00168d392b
3 changed files with 79 additions and 46 deletions

View file

@ -167,7 +167,7 @@
:type "text" :type "text"
:placeholder (t locale "ds.search.placeholder") :placeholder (t locale "ds.search.placeholder")
:default-value search-term-not-nil :default-value search-term-not-nil
:autoComplete "off" :auto-complete "off"
:on-focus on-search-focus :on-focus on-search-focus
:on-change on-search-change :on-change on-search-change
:ref #(when % (set! (.-value %) search-term-not-nil))}] :ref #(when % (set! (.-value %) search-term-not-nil))}]

View file

@ -19,6 +19,7 @@
[uxbox.main.store :as st] [uxbox.main.store :as st]
[uxbox.main.streams :as ms] [uxbox.main.streams :as ms]
[uxbox.util.dom :as dom] [uxbox.util.dom :as dom]
[uxbox.util.object :as obj]
[uxbox.util.geom.point :as gpt] [uxbox.util.geom.point :as gpt]
[uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.matrix :as gmt]
[uxbox.util.debug :refer [debug?]])) [uxbox.util.debug :refer [debug?]]))
@ -32,49 +33,74 @@
60) 60)
(mf/defc control-item (mf/defc control-item
[{:keys [class on-click r cy cx] :as props}] {::mf/wrap-props false}
[:circle [props]
{:class-name class (let [class (obj/get props "class")
:on-mouse-down on-click on-click (obj/get props "on-click")
:r r r (obj/get props "r")
:style {:fillOpacity "1" cx (obj/get props "cx")
:strokeWidth "1px" cy (obj/get props "cy")]
[:circle
{:class-name class
:on-mouse-down on-click
:r r
:style {:fillOpacity "1"
:strokeWidth "1px"
:vectorEffect "non-scaling-stroke"} :vectorEffect "non-scaling-stroke"}
:fill "#ffffff" :fill "#ffffff"
:stroke "#1FDEA7" :stroke "#1FDEA7"
:cx cx :cx cx
:cy cy}]) :cy cy}]))
(def ^:private rotate-cursor-svg "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20px' height='20px' transform='rotate(%s)' viewBox='0 0 132.292 132.006'%3E%3Cpath d='M85.225 3.48c.034 4.989-.093 9.852-.533 14.78-29.218 5.971-54.975 27.9-63.682 56.683-1.51 2.923-1.431 7.632-3.617 9.546-5.825.472-11.544.5-17.393.45 11.047 15.332 20.241 32.328 32.296 46.725 5.632 1.855 7.155-5.529 10.066-8.533 8.12-12.425 17.252-24.318 24.269-37.482-6.25-.86-12.564-.88-18.857-1.057 5.068-17.605 19.763-31.81 37.091-37.122.181 6.402.206 12.825 1.065 19.184 15.838-9.05 30.899-19.617 45.601-30.257 2.985-4.77-3.574-7.681-6.592-9.791C111.753 17.676 98.475 8.889 85.23.046l-.005 3.435z'/%3E%3Cpath fill='%23fff' d='M92.478 23.995s-1.143.906-6.714 1.923c-29.356 5.924-54.352 30.23-59.717 59.973-.605 3.728-1.09 5.49-1.09 5.49l-11.483-.002s7.84 10.845 10.438 15.486c3.333 4.988 6.674 9.971 10.076 14.912a2266.92 2266.92 0 0019.723-29.326c-5.175-.16-10.35-.343-15.522-.572 3.584-27.315 26.742-50.186 53.91-54.096.306 5.297.472 10.628.631 15.91a2206.462 2206.462 0 0029.333-19.726c-9.75-6.7-19.63-13.524-29.483-20.12z'/%3E%3C/svg%3E\") 10 10, auto") (def ^:private rotate-cursor-svg "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20px' height='20px' transform='rotate(%s)' viewBox='0 0 132.292 132.006'%3E%3Cpath d='M85.225 3.48c.034 4.989-.093 9.852-.533 14.78-29.218 5.971-54.975 27.9-63.682 56.683-1.51 2.923-1.431 7.632-3.617 9.546-5.825.472-11.544.5-17.393.45 11.047 15.332 20.241 32.328 32.296 46.725 5.632 1.855 7.155-5.529 10.066-8.533 8.12-12.425 17.252-24.318 24.269-37.482-6.25-.86-12.564-.88-18.857-1.057 5.068-17.605 19.763-31.81 37.091-37.122.181 6.402.206 12.825 1.065 19.184 15.838-9.05 30.899-19.617 45.601-30.257 2.985-4.77-3.574-7.681-6.592-9.791C111.753 17.676 98.475 8.889 85.23.046l-.005 3.435z'/%3E%3Cpath fill='%23fff' d='M92.478 23.995s-1.143.906-6.714 1.923c-29.356 5.924-54.352 30.23-59.717 59.973-.605 3.728-1.09 5.49-1.09 5.49l-11.483-.002s7.84 10.845 10.438 15.486c3.333 4.988 6.674 9.971 10.076 14.912a2266.92 2266.92 0 0019.723-29.326c-5.175-.16-10.35-.343-15.522-.572 3.584-27.315 26.742-50.186 53.91-54.096.306 5.297.472 10.628.631 15.91a2206.462 2206.462 0 0029.333-19.726c-9.75-6.7-19.63-13.524-29.483-20.12z'/%3E%3C/svg%3E\") 10 10, auto")
(defn rotation-cursor
[angle]
(str "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20px' height='20px' transform='rotate(" angle ")' viewBox='0 0 132.292 132.006'%3E%3Cpath d='M85.225 3.48c.034 4.989-.093 9.852-.533 14.78-29.218 5.971-54.975 27.9-63.682 56.683-1.51 2.923-1.431 7.632-3.617 9.546-5.825.472-11.544.5-17.393.45 11.047 15.332 20.241 32.328 32.296 46.725 5.632 1.855 7.155-5.529 10.066-8.533 8.12-12.425 17.252-24.318 24.269-37.482-6.25-.86-12.564-.88-18.857-1.057 5.068-17.605 19.763-31.81 37.091-37.122.181 6.402.206 12.825 1.065 19.184 15.838-9.05 30.899-19.617 45.601-30.257 2.985-4.77-3.574-7.681-6.592-9.791C111.753 17.676 98.475 8.889 85.23.046l-.005 3.435z'/%3E%3Cpath fill='%23fff' d='M92.478 23.995s-1.143.906-6.714 1.923c-29.356 5.924-54.352 30.23-59.717 59.973-.605 3.728-1.09 5.49-1.09 5.49l-11.483-.002s7.84 10.845 10.438 15.486c3.333 4.988 6.674 9.971 10.076 14.912a2266.92 2266.92 0 0019.723-29.326c-5.175-.16-10.35-.343-15.522-.572 3.584-27.315 26.742-50.186 53.91-54.096.306 5.297.472 10.628.631 15.91a2206.462 2206.462 0 0029.333-19.726c-9.75-6.7-19.63-13.524-29.483-20.12z'/%3E%3C/svg%3E\") 10 10, auto"))
(def rotation-handler-positions
#{:top-left :top-right :bottom-left :bottom-right})
(mf/defc rotation-handler (mf/defc rotation-handler
[{:keys [cx cy position on-mouse-down rotation zoom]}] {::mf/wrap-props false}
(when (#{:top-left :top-right :bottom-left :bottom-right} position) [props]
(let [size (/ 20 zoom) (let [cx (obj/get props "cx")
rotation (or rotation 0) cy (obj/get props "cy")
x (- cx (if (#{:top-left :bottom-left} position) size 0)) position (obj/get props "position")
y (- cy (if (#{:top-left :top-right} position) size 0)) on-mouse-down (obj/get props "on-mouse-down")
angle (case position rotation (obj/get props "rotation")
:top-left 0 zoom (obj/get props "zoom")]
:top-right 90 (when (contains? rotation-handler-positions position)
:bottom-right 180 (let [size (/ 20 zoom)
:bottom-left 270)] rotation (or rotation 0)
[:rect {:style {:cursor (str/format rotate-cursor-svg (str (+ rotation angle)))} x (- cx (if (#{:top-left :bottom-left} position) size 0))
:x x y (- cy (if (#{:top-left :top-right} position) size 0))
:y y angle (case position
:width size :top-left 0
:height size :top-right 90
:fill (if (debug? :rotation-handler) "red" "transparent") :bottom-right 180
:transform (gmt/rotate-matrix rotation (gpt/point cx cy)) :bottom-left 270)]
:on-mouse-down (or on-mouse-down (fn []))}]))) [:rect {:style {:cursor (rotation-cursor (+ rotation angle))}
:x x
:y y
:width size
:height size
:fill (if (debug? :rotation-handler) "red" "transparent")
:transform (gmt/rotate-matrix rotation (gpt/point cx cy))
:on-mouse-down (or on-mouse-down (fn []))}]))))
(mf/defc controls (mf/defc controls
[{:keys [shape zoom on-resize on-rotate] :as props}] {::mf/wrap-props false}
(let [{:keys [x y width height rotation] :as shape} (geom/shape->rect-shape shape) [props]
(let [shape (obj/get props "shape")
zoom (obj/get props "zoom")
on-resize (obj/get props "on-resize")
on-rotate (obj/get props "on-rotate")
{:keys [x y width height rotation] :as shape} (geom/shape->rect-shape shape)
radius (if (> (max width height) handler-size-threshold) 4.0 4.0) radius (if (> (max width height) handler-size-threshold) 4.0 4.0)
transform (geom/transform-matrix shape) transform (geom/transform-matrix shape)
resize-handlers {:top [(+ x (/ width 2 )) y] resize-handlers {:top [(+ x (/ width 2 )) y]
:right [(+ x width) (+ y (/ height 2))] :right [(+ x width) (+ y (/ height 2))]
:bottom [(+ x (/ width 2)) (+ y height)] :bottom [(+ x (/ width 2)) (+ y height)]
@ -83,7 +109,7 @@
:top-right [(+ x width) y] :top-right [(+ x width) y]
:bottom-left [x (+ y height)] :bottom-left [x (+ y height)]
:bottom-right [(+ x width) (+ y height)]}] :bottom-right [(+ x width) (+ y height)]}]
[:g.controls [:g.controls
[:rect.main {:transform transform [:rect.main {:transform transform
:x (- x 1) :y (- y 1) :x (- x 1) :y (- y 1)
@ -95,17 +121,15 @@
(for [[position [cx cy]] resize-handlers] (for [[position [cx cy]] resize-handlers]
(let [tp (gpt/transform (gpt/point cx cy) transform)] (let [tp (gpt/transform (gpt/point cx cy) transform)]
[:* {:key (str "fragment-" (name position))} [:* {:key (name position)}
[:& rotation-handler {:key (str "rotation-" (name position)) [:& rotation-handler {:cx (:x tp)
:cx (:x tp)
:cy (:y tp) :cy (:y tp)
:position position :position position
:rotation (:rotation shape) :rotation (:rotation shape)
:zoom zoom :zoom zoom
:on-mouse-down on-rotate}] :on-mouse-down on-rotate}]
[:& control-item {:key (str "resize-" (name position)) [:& control-item {:class (name position)
:class (name position)
:on-click #(on-resize position %) :on-click #(on-resize position %)
:r (/ radius zoom) :r (/ radius zoom)
:cx (:x tp) :cx (:x tp)
@ -170,6 +194,7 @@
[{:keys [shapes selected zoom objects] :as props}] [{:keys [shapes selected zoom objects] :as props}]
(let [shape (geom/selection-rect shapes) (let [shape (geom/selection-rect shapes)
shape-center (geom/center shape) shape-center (geom/center shape)
on-resize #(do (dom/stop-propagation %2) on-resize #(do (dom/stop-propagation %2)
(st/emit! (dw/start-resize %1 selected shape objects))) (st/emit! (dw/start-resize %1 selected shape objects)))
@ -189,11 +214,18 @@
(let [shape-id (:id shape) (let [shape-id (:id shape)
shape (geom/transform-shape shape) shape (geom/transform-shape shape)
shape' (if (debug? :simple-selection) (geom/selection-rect [shape]) shape) shape' (if (debug? :simple-selection) (geom/selection-rect [shape]) shape)
on-resize #(do (dom/stop-propagation %2)
(st/emit! (dw/start-resize %1 #{shape-id} shape' objects)))
on-rotate #(do (dom/stop-propagation %)
(st/emit! (dw/start-rotate [shape])))]
on-resize
(mf/use-callback
(mf/deps shape-id)
#(do (dom/stop-propagation %2)
(st/emit! (dw/start-resize %1 #{shape-id} shape' objects))))
on-rotate
(mf/use-callback
(mf/deps shape-id)
#(do (dom/stop-propagation %)
(st/emit! (dw/start-rotate [shape]))))]
[:& controls {:shape shape' [:& controls {:shape shape'
:zoom zoom :zoom zoom
:on-rotate on-rotate :on-rotate on-rotate

View file

@ -465,7 +465,8 @@
(declare transform-apply-modifiers) (declare transform-apply-modifiers)
(defn selection-rect-shape [shape] (defn selection-rect-shape
[shape]
(-> shape (-> shape
(transform-apply-modifiers) (transform-apply-modifiers)
(shape->rect-shape))) (shape->rect-shape)))