mirror of
https://github.com/penpot/penpot.git
synced 2025-01-24 07:29:08 -05:00
⚡ Removed reflow in viewport
This commit is contained in:
parent
333acacbbf
commit
d5ab0eea1a
6 changed files with 111 additions and 62 deletions
|
@ -40,6 +40,7 @@
|
|||
[app.main.ui.workspace.viewport.snap-distances :as snap-distances]
|
||||
[app.main.ui.workspace.viewport.snap-points :as snap-points]
|
||||
[app.main.ui.workspace.viewport.utils :as utils]
|
||||
[app.main.ui.workspace.viewport.viewport-ref :refer [create-viewport-ref]]
|
||||
[app.main.ui.workspace.viewport.widgets :as widgets]
|
||||
[beicon.core :as rx]
|
||||
[debug :refer [debug?]]
|
||||
|
@ -98,7 +99,8 @@
|
|||
active-frames (mf/use-state #{})
|
||||
|
||||
;; REFS
|
||||
viewport-ref (mf/use-ref nil)
|
||||
[viewport-ref
|
||||
on-viewport-ref] (create-viewport-ref)
|
||||
|
||||
;; VARS
|
||||
disable-paste (mf/use-var false)
|
||||
|
@ -140,15 +142,14 @@
|
|||
on-double-click (actions/on-double-click hover hover-ids drawing-path? base-objects edition workspace-read-only?)
|
||||
on-drag-enter (actions/on-drag-enter)
|
||||
on-drag-over (actions/on-drag-over)
|
||||
on-drop (actions/on-drop file viewport-ref zoom)
|
||||
on-drop (actions/on-drop file)
|
||||
on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing?
|
||||
drawing-path? create-comment? space? viewport-ref zoom panning
|
||||
workspace-read-only?)
|
||||
drawing-path? create-comment? space? panning workspace-read-only?)
|
||||
on-mouse-up (actions/on-mouse-up disable-paste)
|
||||
on-pointer-down (actions/on-pointer-down)
|
||||
on-pointer-enter (actions/on-pointer-enter in-viewport?)
|
||||
on-pointer-leave (actions/on-pointer-leave in-viewport?)
|
||||
on-pointer-move (actions/on-pointer-move viewport-ref zoom move-stream)
|
||||
on-pointer-move (actions/on-pointer-move move-stream)
|
||||
on-pointer-up (actions/on-pointer-up)
|
||||
on-move-selected (actions/on-move-selected hover hover-ids selected space? workspace-read-only?)
|
||||
on-menu-selected (actions/on-menu-selected hover hover-ids selected workspace-read-only?)
|
||||
|
@ -269,7 +270,7 @@
|
|||
:preserveAspectRatio "xMidYMid meet"
|
||||
:key (str "viewport" page-id)
|
||||
:view-box (utils/format-viewbox vbox)
|
||||
:ref viewport-ref
|
||||
:ref on-viewport-ref
|
||||
:class (when drawing-tool "drawing")
|
||||
:style {:cursor @cursor}
|
||||
:fill "none"
|
||||
|
@ -423,8 +424,7 @@
|
|||
[:& scroll-bars/viewport-scrollbars
|
||||
{:objects base-objects
|
||||
:zoom zoom
|
||||
:vbox vbox
|
||||
:viewport-ref viewport-ref}]
|
||||
:vbox vbox}]
|
||||
|
||||
(when show-rules?
|
||||
[:& rules/rules
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.ui.workspace.viewport.utils :as utils]
|
||||
[app.main.ui.workspace.viewport.viewport-ref :as uwvv]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.dom.dnd :as dnd]
|
||||
[app.util.dom.normalize-wheel :as nw]
|
||||
|
@ -34,11 +34,11 @@
|
|||
|
||||
(defn on-mouse-down
|
||||
[{:keys [id blocked hidden type]} selected edition drawing-tool text-editing?
|
||||
node-editing? drawing-path? create-comment? space? viewport-ref zoom panning
|
||||
node-editing? drawing-path? create-comment? space? panning
|
||||
workspace-read-only?]
|
||||
(mf/use-callback
|
||||
(mf/deps id blocked hidden type selected edition drawing-tool text-editing?
|
||||
node-editing? drawing-path? create-comment? @space? viewport-ref zoom
|
||||
node-editing? drawing-path? create-comment? @space?
|
||||
panning workspace-read-only?)
|
||||
(fn [bevent]
|
||||
(when (or (dom/class? (dom/get-target bevent) "viewport-controls")
|
||||
|
@ -61,8 +61,7 @@
|
|||
(dom/prevent-default bevent)
|
||||
(if mod?
|
||||
(let [raw-pt (dom/get-client-position event)
|
||||
viewport (mf/ref-val viewport-ref)
|
||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
||||
pt (uwvv/point->viewport raw-pt)]
|
||||
(st/emit! (dw/start-zooming pt)))
|
||||
(st/emit! (dw/start-panning))))
|
||||
|
||||
|
@ -322,15 +321,12 @@
|
|||
(= "TEXTAREA" (obj/get target "tagName")))]
|
||||
(st/emit! (ms/->KeyboardEvent :up key shift? ctrl? alt? meta? editing?))))))
|
||||
|
||||
(defn on-mouse-move [viewport-ref zoom]
|
||||
(defn on-mouse-move []
|
||||
(let [last-position (mf/use-var nil)]
|
||||
(mf/use-callback
|
||||
(mf/deps zoom)
|
||||
(fn [event]
|
||||
(let [event (.getBrowserEvent ^js event)
|
||||
raw-pt (dom/get-client-position event)
|
||||
viewport (mf/ref-val viewport-ref)
|
||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)
|
||||
(let [raw-pt (dom/get-client-position event)
|
||||
pt (uwvv/point->viewport raw-pt)
|
||||
|
||||
;; We calculate the delta because Safari's MouseEvent.movementX/Y drop
|
||||
;; events
|
||||
|
@ -350,30 +346,27 @@
|
|||
(kbd/alt? event)
|
||||
(kbd/meta? event))))))))
|
||||
|
||||
(defn on-pointer-move [viewport-ref zoom move-stream]
|
||||
(defn on-pointer-move [move-stream]
|
||||
(mf/use-callback
|
||||
(mf/deps zoom move-stream)
|
||||
(mf/deps move-stream)
|
||||
(fn [event]
|
||||
(let [raw-pt (dom/get-client-position event)
|
||||
viewport (mf/ref-val viewport-ref)
|
||||
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
|
||||
pt (uwvv/point->viewport raw-pt)]
|
||||
(rx/push! move-stream pt)))))
|
||||
|
||||
(defn on-mouse-wheel [viewport-ref zoom]
|
||||
(defn on-mouse-wheel [zoom]
|
||||
(mf/use-callback
|
||||
(mf/deps zoom)
|
||||
(fn [event]
|
||||
(let [viewport (mf/ref-val viewport-ref)
|
||||
event (.getBrowserEvent ^js event)
|
||||
(let [event (.getBrowserEvent ^js event)
|
||||
target (dom/get-target event)
|
||||
mod? (kbd/mod? event)]
|
||||
|
||||
(when (dom/is-child? viewport target)
|
||||
(when (uwvv/inside-viewport? target)
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(let [pt (->> (dom/get-client-position event)
|
||||
(utils/translate-point-to-viewport viewport zoom))
|
||||
|
||||
(let [raw-pt (dom/get-client-position event)
|
||||
pt (uwvv/point->viewport raw-pt)
|
||||
norm-event ^js (nw/normalize-wheel event)
|
||||
ctrl? (kbd/ctrl? event)
|
||||
delta-y (.-pixelY norm-event)
|
||||
|
@ -413,14 +406,12 @@
|
|||
(dom/prevent-default e)))))
|
||||
|
||||
(defn on-drop
|
||||
[file viewport-ref zoom]
|
||||
[file]
|
||||
(mf/use-fn
|
||||
(mf/deps zoom)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(let [point (gpt/point (.-clientX event) (.-clientY event))
|
||||
viewport (mf/ref-val viewport-ref)
|
||||
viewport-coord (utils/translate-point-to-viewport viewport zoom point)
|
||||
viewport-coord (uwvv/point->viewport point)
|
||||
asset-id (-> (dnd/get-data event "text/asset-id") uuid/uuid)
|
||||
asset-name (dnd/get-data event "text/asset-name")
|
||||
asset-type (dnd/get-data event "text/asset-type")]
|
||||
|
|
|
@ -35,21 +35,29 @@
|
|||
(defn setup-dom-events [viewport-ref zoom disable-paste in-viewport? workspace-read-only?]
|
||||
(let [on-key-down (actions/on-key-down)
|
||||
on-key-up (actions/on-key-up)
|
||||
on-mouse-move (actions/on-mouse-move viewport-ref zoom)
|
||||
on-mouse-wheel (actions/on-mouse-wheel viewport-ref zoom)
|
||||
on-mouse-move (actions/on-mouse-move)
|
||||
on-mouse-wheel (actions/on-mouse-wheel zoom)
|
||||
on-paste (actions/on-paste disable-paste in-viewport? workspace-read-only?)]
|
||||
|
||||
;; We use the DOM listener because the goog.closure one forces reflow to generate its internal
|
||||
;; structure. As we don't need currently nothing from BrowserEvent we optimize by using the basic event
|
||||
(mf/use-layout-effect
|
||||
(mf/deps on-mouse-move)
|
||||
(fn []
|
||||
(let [node (mf/ref-val viewport-ref)]
|
||||
(.addEventListener node "mousemove" on-mouse-move)
|
||||
(fn []
|
||||
(.removeEventListener node "mousemove" on-mouse-move)))))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps on-key-down on-key-up on-mouse-move on-mouse-wheel on-paste workspace-read-only?)
|
||||
(fn []
|
||||
(let [node (mf/ref-val viewport-ref)
|
||||
keys [(events/listen js/document EventType.KEYDOWN on-key-down)
|
||||
(let [keys [(events/listen js/document EventType.KEYDOWN on-key-down)
|
||||
(events/listen js/document EventType.KEYUP on-key-up)
|
||||
(events/listen node EventType.MOUSEMOVE on-mouse-move)
|
||||
;; bind with passive=false to allow the event to be cancelled
|
||||
;; https://stackoverflow.com/a/57582286/3219895
|
||||
(events/listen js/window EventType.WHEEL on-mouse-wheel #js {:passive false})
|
||||
(events/listen js/window EventType.PASTE on-paste)]]
|
||||
|
||||
(fn []
|
||||
(doseq [key keys]
|
||||
(events/unlistenByKey key))))))))
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.workspace.viewport.utils :as utils]
|
||||
[app.main.ui.workspace.viewport.viewport-ref :refer [point->viewport]]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
|||
|
||||
(mf/defc viewport-scrollbars
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [objects viewport-ref zoom vbox]}]
|
||||
[{:keys [objects zoom vbox]}]
|
||||
|
||||
(let [v-scrolling? (mf/use-state false)
|
||||
h-scrolling? (mf/use-state false)
|
||||
|
@ -126,10 +126,9 @@
|
|||
on-mouse-move
|
||||
(fn [event axis]
|
||||
(when-let [_ (or @v-scrolling? @h-scrolling?)]
|
||||
(let [viewport (mf/ref-val viewport-ref)
|
||||
start-pt (mf/ref-val start-ref)
|
||||
(let [start-pt (mf/ref-val start-ref)
|
||||
current-pt (dom/get-client-position event)
|
||||
current-pt-viewport (utils/translate-point-to-viewport viewport zoom current-pt)
|
||||
current-pt-viewport (point->viewport current-pt)
|
||||
y-delta (/ (* (mf/ref-val height-factor-ref) (- (:y current-pt) (:y start-pt))) zoom)
|
||||
x-delta (/ (* (mf/ref-val width-factor-ref) (- (:x current-pt) (:x start-pt))) zoom)
|
||||
new-v-scrollbar-y (-> current-pt-viewport
|
||||
|
@ -150,9 +149,8 @@
|
|||
|
||||
on-mouse-down
|
||||
(fn [event axis]
|
||||
(let [viewport (mf/ref-val viewport-ref)
|
||||
start-pt (dom/get-client-position event)
|
||||
viewport-point (utils/translate-point-to-viewport viewport zoom start-pt)
|
||||
(let [start-pt (dom/get-client-position event)
|
||||
viewport-point (point->viewport start-pt)
|
||||
new-h-scrollbar-x (:x viewport-point)
|
||||
new-v-scrollbar-y (:y viewport-point)
|
||||
v-scrollbar-y-padding (- v-scrollbar-y new-v-scrollbar-y)
|
||||
|
|
|
@ -6,13 +6,11 @@
|
|||
|
||||
(ns app.main.ui.workspace.viewport.utils
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.main.ui.cursors :as cur]
|
||||
[app.main.ui.formats :refer [format-number]]
|
||||
[app.util.dom :as dom]))
|
||||
[app.main.ui.formats :refer [format-number]]))
|
||||
|
||||
(defn format-viewbox [vbox]
|
||||
(dm/str (format-number(:x vbox 0)) " "
|
||||
|
@ -20,17 +18,6 @@
|
|||
(format-number (:width vbox 0)) " "
|
||||
(format-number (:height vbox 0))))
|
||||
|
||||
(defn translate-point-to-viewport [viewport zoom pt]
|
||||
(let [vbox (.. ^js viewport -viewBox -baseVal)
|
||||
brect (dom/get-bounding-rect viewport)
|
||||
brect (gpt/point (d/parse-integer (:left brect))
|
||||
(d/parse-integer (:top brect)))
|
||||
box (gpt/point (.-x vbox) (.-y vbox))
|
||||
zoom (gpt/point zoom)]
|
||||
(-> (gpt/subtract pt brect)
|
||||
(gpt/divide zoom)
|
||||
(gpt/add box))))
|
||||
|
||||
(defn get-cursor [cursor]
|
||||
(case cursor
|
||||
:hand cur/hand
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.viewport.viewport-ref
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.main.store :as st]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defonce viewport-ref (atom nil))
|
||||
(defonce current-observer (atom nil))
|
||||
(defonce viewport-brect (atom nil))
|
||||
|
||||
(defn init-observer
|
||||
[node on-change-bounds]
|
||||
|
||||
(let [observer (js/ResizeObserver. on-change-bounds)]
|
||||
(when (some? @current-observer)
|
||||
(.disconnect @current-observer))
|
||||
|
||||
(reset! current-observer observer)
|
||||
|
||||
(when (some? node)
|
||||
(.observe observer node))))
|
||||
|
||||
(defn on-change-bounds
|
||||
[_]
|
||||
(when @viewport-ref
|
||||
(let [brect (dom/get-bounding-rect @viewport-ref)
|
||||
brect (gpt/point (d/parse-integer (:left brect))
|
||||
(d/parse-integer (:top brect)))]
|
||||
(reset! viewport-brect brect))))
|
||||
|
||||
(defn create-viewport-ref
|
||||
[]
|
||||
|
||||
(let [ref (mf/use-ref nil)]
|
||||
[ref
|
||||
(mf/use-memo
|
||||
#(fn [node]
|
||||
(mf/set-ref-val! ref node)
|
||||
(reset! viewport-ref node)
|
||||
(init-observer node on-change-bounds)))]))
|
||||
|
||||
(defn point->viewport
|
||||
[pt]
|
||||
(let [zoom (dm/get-in @st/state [:workspace-local :zoom])]
|
||||
(when (some? @viewport-ref)
|
||||
(let [vbox (.. ^js @viewport-ref -viewBox -baseVal)
|
||||
brect @viewport-brect
|
||||
box (gpt/point (.-x vbox) (.-y vbox))
|
||||
zoom (gpt/point zoom)]
|
||||
(-> (gpt/subtract pt brect)
|
||||
(gpt/divide zoom)
|
||||
(gpt/add box))))))
|
||||
|
||||
(defn inside-viewport?
|
||||
[target]
|
||||
(dom/is-child? @viewport-ref target))
|
Loading…
Add table
Reference in a new issue