0
Fork 0
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:
alonso.torres 2023-01-03 16:57:01 +01:00
parent 333acacbbf
commit d5ab0eea1a
6 changed files with 111 additions and 62 deletions

View file

@ -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

View file

@ -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")]

View file

@ -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))))))))

View file

@ -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)

View file

@ -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

View file

@ -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))