From 00168d392bd99dda5bf3d75c5aacb537d072fd10 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 11:07:39 +0200 Subject: [PATCH] :zap: Performance improvements on selection handlers. --- .../src/uxbox/main/ui/dashboard/sidebar.cljs | 2 +- .../uxbox/main/ui/workspace/selection.cljs | 120 +++++++++++------- frontend/src/uxbox/util/geom/shapes.cljs | 3 +- 3 files changed, 79 insertions(+), 46 deletions(-) diff --git a/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs b/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs index 1d718b30e..f7c8f5fef 100644 --- a/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs @@ -167,7 +167,7 @@ :type "text" :placeholder (t locale "ds.search.placeholder") :default-value search-term-not-nil - :autoComplete "off" + :auto-complete "off" :on-focus on-search-focus :on-change on-search-change :ref #(when % (set! (.-value %) search-term-not-nil))}] diff --git a/frontend/src/uxbox/main/ui/workspace/selection.cljs b/frontend/src/uxbox/main/ui/workspace/selection.cljs index 10b9492a1..ae9f1c56a 100644 --- a/frontend/src/uxbox/main/ui/workspace/selection.cljs +++ b/frontend/src/uxbox/main/ui/workspace/selection.cljs @@ -19,6 +19,7 @@ [uxbox.main.store :as st] [uxbox.main.streams :as ms] [uxbox.util.dom :as dom] + [uxbox.util.object :as obj] [uxbox.util.geom.point :as gpt] [uxbox.util.geom.matrix :as gmt] [uxbox.util.debug :refer [debug?]])) @@ -32,49 +33,74 @@ 60) (mf/defc control-item - [{:keys [class on-click r cy cx] :as props}] - [:circle - {:class-name class - :on-mouse-down on-click - :r r - :style {:fillOpacity "1" - :strokeWidth "1px" + {::mf/wrap-props false} + [props] + (let [class (obj/get props "class") + on-click (obj/get props "on-click") + r (obj/get props "r") + cx (obj/get props "cx") + 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"} - :fill "#ffffff" - :stroke "#1FDEA7" - :cx cx - :cy cy}]) + :fill "#ffffff" + :stroke "#1FDEA7" + :cx cx + :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") +(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 - [{:keys [cx cy position on-mouse-down rotation zoom]}] - (when (#{:top-left :top-right :bottom-left :bottom-right} position) - (let [size (/ 20 zoom) - rotation (or rotation 0) - x (- cx (if (#{:top-left :bottom-left} position) size 0)) - y (- cy (if (#{:top-left :top-right} position) size 0)) - angle (case position - :top-left 0 - :top-right 90 - :bottom-right 180 - :bottom-left 270)] - [:rect {:style {:cursor (str/format rotate-cursor-svg (str (+ 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/wrap-props false} + [props] + (let [cx (obj/get props "cx") + cy (obj/get props "cy") + position (obj/get props "position") + on-mouse-down (obj/get props "on-mouse-down") + rotation (obj/get props "rotation") + zoom (obj/get props "zoom")] + (when (contains? rotation-handler-positions position) + (let [size (/ 20 zoom) + rotation (or rotation 0) + x (- cx (if (#{:top-left :bottom-left} position) size 0)) + y (- cy (if (#{:top-left :top-right} position) size 0)) + angle (case position + :top-left 0 + :top-right 90 + :bottom-right 180 + :bottom-left 270)] + [: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 - [{:keys [shape zoom on-resize on-rotate] :as props}] - (let [{:keys [x y width height rotation] :as shape} (geom/shape->rect-shape shape) + {::mf/wrap-props false} + [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) - transform (geom/transform-matrix shape) - resize-handlers {:top [(+ x (/ width 2 )) y] :right [(+ x width) (+ y (/ height 2))] :bottom [(+ x (/ width 2)) (+ y height)] @@ -83,7 +109,7 @@ :top-right [(+ x width) y] :bottom-left [x (+ y height)] :bottom-right [(+ x width) (+ y height)]}] - + [:g.controls [:rect.main {:transform transform :x (- x 1) :y (- y 1) @@ -95,17 +121,15 @@ (for [[position [cx cy]] resize-handlers] (let [tp (gpt/transform (gpt/point cx cy) transform)] - [:* {:key (str "fragment-" (name position))} - [:& rotation-handler {:key (str "rotation-" (name position)) - :cx (:x tp) + [:* {:key (name position)} + [:& rotation-handler {:cx (:x tp) :cy (:y tp) :position position :rotation (:rotation shape) :zoom zoom :on-mouse-down on-rotate}] - [:& control-item {:key (str "resize-" (name position)) - :class (name position) + [:& control-item {:class (name position) :on-click #(on-resize position %) :r (/ radius zoom) :cx (:x tp) @@ -170,6 +194,7 @@ [{:keys [shapes selected zoom objects] :as props}] (let [shape (geom/selection-rect shapes) shape-center (geom/center shape) + on-resize #(do (dom/stop-propagation %2) (st/emit! (dw/start-resize %1 selected shape objects))) @@ -189,11 +214,18 @@ (let [shape-id (:id shape) shape (geom/transform-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' :zoom zoom :on-rotate on-rotate diff --git a/frontend/src/uxbox/util/geom/shapes.cljs b/frontend/src/uxbox/util/geom/shapes.cljs index 6f08ba976..f0e20c777 100644 --- a/frontend/src/uxbox/util/geom/shapes.cljs +++ b/frontend/src/uxbox/util/geom/shapes.cljs @@ -465,7 +465,8 @@ (declare transform-apply-modifiers) -(defn selection-rect-shape [shape] +(defn selection-rect-shape + [shape] (-> shape (transform-apply-modifiers) (shape->rect-shape)))