mirror of
https://github.com/penpot/penpot.git
synced 2025-05-05 21:16:00 +02:00
🎉 Improve viewer performance degradation because of fixed position
This commit is contained in:
parent
f736ec813e
commit
108cdcecbb
7 changed files with 91 additions and 85 deletions
|
@ -171,6 +171,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewport-container {
|
.viewport-container {
|
||||||
|
clip-path: inset(0 0 0 0);
|
||||||
grid-column: 1 / 1;
|
grid-column: 1 / 1;
|
||||||
grid-row: 1 / 1;
|
grid-row: 1 / 1;
|
||||||
|
|
||||||
|
.not-fixed {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed {
|
||||||
|
position: fixed;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
.frame-children g {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,21 +42,13 @@
|
||||||
(if masked-group?
|
(if masked-group?
|
||||||
["g" (-> (obj/create)
|
["g" (-> (obj/create)
|
||||||
(obj/set! "mask" (mask-url render-id mask)))]
|
(obj/set! "mask" (mask-url render-id mask)))]
|
||||||
[mf/Fragment nil])
|
[mf/Fragment nil])]
|
||||||
|
|
||||||
;; This factory is generic, it's used for viewer, workspace and handoff.
|
|
||||||
;; These props are generated in viewer wrappers only, in the rest of the
|
|
||||||
;; cases these props will be nil, not affecting the code.
|
|
||||||
delta (unchecked-get props "delta")
|
|
||||||
fixed? (unchecked-get props "fixed?")]
|
|
||||||
|
|
||||||
[:> clip-wrapper clip-props
|
[:> clip-wrapper clip-props
|
||||||
[:> mask-wrapper mask-props
|
[:> mask-wrapper mask-props
|
||||||
(when masked-group?
|
(when masked-group?
|
||||||
[:> render-mask #js {:mask mask
|
[:> render-mask #js {:mask mask
|
||||||
:objects objects
|
:objects objects}])
|
||||||
:delta delta
|
|
||||||
:fixed? fixed?}])
|
|
||||||
|
|
||||||
(for [item childs]
|
(for [item childs]
|
||||||
[:& shape-wrapper {:shape item
|
[:& shape-wrapper {:shape item
|
||||||
|
|
|
@ -50,13 +50,7 @@
|
||||||
render-id (mf/use-ctx muc/render-id)
|
render-id (mf/use-ctx muc/render-id)
|
||||||
svg-text? (and (= :text (:type mask)) (some? (:position-data mask)))
|
svg-text? (and (= :text (:type mask)) (some? (:position-data mask)))
|
||||||
|
|
||||||
;; This factory is generic, it's used for viewer, workspace and handoff.
|
|
||||||
;; These props are generated in viewer wrappers only, in the rest of the
|
|
||||||
;; cases these props will be nil, not affecting the code.
|
|
||||||
fixed? (unchecked-get props "fixed?")
|
|
||||||
delta (unchecked-get props "delta")
|
|
||||||
mask-bb (-> (gsh/transform-shape mask)
|
mask-bb (-> (gsh/transform-shape mask)
|
||||||
(cond-> fixed? (gsh/move delta))
|
|
||||||
(:points))
|
(:points))
|
||||||
|
|
||||||
mask-bb-rect (gsh/points->rect mask-bb)]
|
mask-bb-rect (gsh/points->rect mask-bb)]
|
||||||
|
|
|
@ -255,7 +255,6 @@
|
||||||
|
|
||||||
fullscreen? (mf/deref header/fullscreen-ref)
|
fullscreen? (mf/deref header/fullscreen-ref)
|
||||||
overlays (mf/deref current-overlays-ref)
|
overlays (mf/deref current-overlays-ref)
|
||||||
scroll (mf/use-state nil)
|
|
||||||
|
|
||||||
orig-frame
|
orig-frame
|
||||||
(mf/with-memo [current-animations]
|
(mf/with-memo [current-animations]
|
||||||
|
@ -309,11 +308,6 @@
|
||||||
size (dom/get-client-size viewer-section)]
|
size (dom/get-client-size viewer-section)]
|
||||||
(st/emit! (dv/set-viewport-size {:size size})))))
|
(st/emit! (dv/set-viewport-size {:size size})))))
|
||||||
|
|
||||||
on-scroll
|
|
||||||
(mf/use-fn
|
|
||||||
(fn [event]
|
|
||||||
(reset! scroll (dom/get-target-scroll event))))
|
|
||||||
|
|
||||||
on-wheel
|
on-wheel
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
|
@ -354,12 +348,10 @@
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(dom/set-html-theme-color clr/gray-50 "dark")
|
(dom/set-html-theme-color clr/gray-50 "dark")
|
||||||
(let [key1 (events/listen js/window "click" on-click)
|
(let [key1 (events/listen js/window "click" on-click)
|
||||||
key2 (events/listen (mf/ref-val viewer-section-ref) "scroll" on-scroll #js {"passive" true})
|
key2 (events/listen (mf/ref-val viewer-section-ref) "wheel" on-wheel #js {"passive" false})]
|
||||||
key3 (events/listen (mf/ref-val viewer-section-ref) "wheel" on-wheel #js {"passive" false})]
|
|
||||||
(fn []
|
(fn []
|
||||||
(events/unlistenByKey key1)
|
(events/unlistenByKey key1)
|
||||||
(events/unlistenByKey key2)
|
(events/unlistenByKey key2))))
|
||||||
(events/unlistenByKey key3))))
|
|
||||||
|
|
||||||
(mf/use-layout-effect
|
(mf/use-layout-effect
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -499,24 +491,24 @@
|
||||||
:index index
|
:index index
|
||||||
:viewer-pagination viewer-pagination}]
|
:viewer-pagination viewer-pagination}]
|
||||||
|
|
||||||
[:& (mf/provider ctx/current-scroll) {:value @scroll}
|
|
||||||
[:& (mf/provider ctx/current-zoom) {:value zoom}
|
[:& (mf/provider ctx/current-zoom) {:value zoom}
|
||||||
[:& viewer-wrapper
|
[:& viewer-wrapper
|
||||||
{:wrapper-size wrapper-size
|
{:wrapper-size wrapper-size
|
||||||
:orig-frame orig-frame
|
:orig-frame orig-frame
|
||||||
:orig-viewport-ref orig-viewport-ref
|
:orig-viewport-ref orig-viewport-ref
|
||||||
:orig-size orig-size
|
:orig-size orig-size
|
||||||
:page page
|
:page page
|
||||||
:file file
|
:file file
|
||||||
:users users
|
:users users
|
||||||
:current-viewport-ref current-viewport-ref
|
:current-viewport-ref current-viewport-ref
|
||||||
:size size
|
:size size
|
||||||
:frame frame
|
:frame frame
|
||||||
:interactions-mode interactions-mode
|
:interactions-mode interactions-mode
|
||||||
:overlays overlays
|
:overlays overlays
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:section section
|
:section section
|
||||||
:index index}]]]))]]]))
|
:index index}]]))]]]))
|
||||||
|
|
||||||
;; --- Component: Viewer Page
|
;; --- Component: Viewer Page
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@
|
||||||
(mf/defc render-frame-svg
|
(mf/defc render-frame-svg
|
||||||
[{:keys [page frame local size]}]
|
[{:keys [page frame local size]}]
|
||||||
(let [objects (mf/with-memo [page frame size]
|
(let [objects (mf/with-memo [page frame size]
|
||||||
(prepare-objects page frame size))
|
(prepare-objects frame size (:objects page)))
|
||||||
|
|
||||||
;; Retrieve frame again with correct modifier
|
;; Retrieve frame again with correct modifier
|
||||||
frame (get objects (:id frame))
|
frame (get objects (:id frame))
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.comments :as dcm]
|
[app.main.data.comments :as dcm]
|
||||||
[app.main.data.viewer :as dv]
|
[app.main.data.viewer :as dv]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -27,8 +28,8 @@
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
(defn prepare-objects
|
(defn prepare-objects
|
||||||
[page frame size]
|
[frame size objects]
|
||||||
(let [objects (:objects page)
|
(let [
|
||||||
frame-id (:id frame)
|
frame-id (:id frame)
|
||||||
modifier (-> (gpt/point (:x size) (:y size))
|
modifier (-> (gpt/point (:x size) (:y size))
|
||||||
(gpt/negate)
|
(gpt/negate)
|
||||||
|
@ -52,26 +53,60 @@
|
||||||
|
|
||||||
vbox (:vbox size)
|
vbox (:vbox size)
|
||||||
|
|
||||||
objects (mf/with-memo [page frame size]
|
fixed-ids (filter :fixed-scroll (vals (:objects page)))
|
||||||
(prepare-objects page frame size))
|
|
||||||
|
|
||||||
wrapper (mf/with-memo [objects]
|
;; we have con consider the children if the fixed element is a group
|
||||||
(shapes/frame-container-factory objects))
|
fixed-children-ids (into #{} (mapcat #(cph/get-children-ids (:objects page) (:id %)) fixed-ids))
|
||||||
|
|
||||||
|
parent-children-ids (->> fixed-ids
|
||||||
|
(mapcat #(cons (:id %) (cph/get-parent-ids (:objects page) (:id %))))
|
||||||
|
(remove #(= % uuid/zero)))
|
||||||
|
|
||||||
|
fixed-ids (concat fixed-children-ids parent-children-ids)
|
||||||
|
|
||||||
|
not-fixed-ids (->> (remove (set fixed-ids) (keys (:objects page)))
|
||||||
|
(remove #(= % uuid/zero)))
|
||||||
|
|
||||||
|
calculate-objects (fn [ids] (->> ids
|
||||||
|
(map (d/getf (:objects page)))
|
||||||
|
(concat [frame])
|
||||||
|
(d/index-by :id)
|
||||||
|
(prepare-objects frame size)))
|
||||||
|
|
||||||
|
wrapper-fixed (mf/with-memo [page frame size]
|
||||||
|
(shapes/frame-container-factory (calculate-objects fixed-ids)))
|
||||||
|
|
||||||
|
objects-not-fixed (mf/with-memo [page frame size]
|
||||||
|
(calculate-objects not-fixed-ids))
|
||||||
|
|
||||||
|
wrapper-not-fixed (mf/with-memo [objects-not-fixed]
|
||||||
|
(shapes/frame-container-factory objects-not-fixed))
|
||||||
|
|
||||||
;; Retrieve frames again with correct modifier
|
;; Retrieve frames again with correct modifier
|
||||||
frame (get objects (:id frame))
|
frame (get objects-not-fixed (:id frame))
|
||||||
base (get objects (:id base))]
|
base (get objects-not-fixed (:id base))]
|
||||||
|
|
||||||
[:& (mf/provider shapes/base-frame-ctx) {:value base}
|
[:& (mf/provider shapes/base-frame-ctx) {:value base}
|
||||||
[:& (mf/provider shapes/frame-offset-ctx) {:value offset}
|
[:& (mf/provider shapes/frame-offset-ctx) {:value offset}
|
||||||
[:svg {:view-box vbox
|
;; We have two different svgs for fixed and not fixed elements so we can emulate the sticky css attribute in svg
|
||||||
:width (:width size)
|
[:svg.not-fixed {:view-box vbox
|
||||||
:height (:height size)
|
:width (:width size)
|
||||||
:version "1.1"
|
:height (:height size)
|
||||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
:version "1.1"
|
||||||
:xmlns "http://www.w3.org/2000/svg"
|
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||||
:fill "none"}
|
:xmlns "http://www.w3.org/2000/svg"
|
||||||
[:& wrapper {:shape frame :view-box vbox}]]]]))
|
:fill "none"}
|
||||||
|
[:& wrapper-not-fixed {:shape frame :view-box vbox}]]
|
||||||
|
[:svg.fixed {:view-box vbox
|
||||||
|
:width (:width size)
|
||||||
|
:height (:height size)
|
||||||
|
:version "1.1"
|
||||||
|
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||||
|
:xmlns "http://www.w3.org/2000/svg"
|
||||||
|
:fill "none"
|
||||||
|
:style {:width (:width size)
|
||||||
|
:height (:height size)}}
|
||||||
|
[:& wrapper-fixed {:shape (dissoc frame :fills) :view-box vbox}]]]]))
|
||||||
|
|
||||||
(mf/defc viewport
|
(mf/defc viewport
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
|
|
|
@ -7,14 +7,12 @@
|
||||||
(ns app.main.ui.viewer.shapes
|
(ns app.main.ui.viewer.shapes
|
||||||
"The main container for a frame in viewer mode"
|
"The main container for a frame in viewer mode"
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.types.shape.interactions :as ctsi]
|
[app.common.types.shape.interactions :as ctsi]
|
||||||
[app.main.data.viewer :as dv]
|
[app.main.data.viewer :as dv]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.context :as ctx]
|
|
||||||
[app.main.ui.shapes.bool :as bool]
|
[app.main.ui.shapes.bool :as bool]
|
||||||
[app.main.ui.shapes.circle :as circle]
|
[app.main.ui.shapes.circle :as circle]
|
||||||
[app.main.ui.shapes.frame :as frame]
|
[app.main.ui.shapes.frame :as frame]
|
||||||
|
@ -223,8 +221,6 @@
|
||||||
childs (unchecked-get props "childs")
|
childs (unchecked-get props "childs")
|
||||||
frame (unchecked-get props "frame")
|
frame (unchecked-get props "frame")
|
||||||
objects (unchecked-get props "objects")
|
objects (unchecked-get props "objects")
|
||||||
fixed? (unchecked-get props "fixed?")
|
|
||||||
delta (unchecked-get props "delta")
|
|
||||||
base-frame (mf/use-ctx base-frame-ctx)
|
base-frame (mf/use-ctx base-frame-ctx)
|
||||||
frame-offset (mf/use-ctx frame-offset-ctx)
|
frame-offset (mf/use-ctx frame-offset-ctx)
|
||||||
|
|
||||||
|
@ -269,9 +265,7 @@
|
||||||
:frame frame
|
:frame frame
|
||||||
:childs childs
|
:childs childs
|
||||||
:is-child-selected? true
|
:is-child-selected? true
|
||||||
:objects objects
|
:objects objects}]
|
||||||
:fixed? fixed?
|
|
||||||
:delta delta}]
|
|
||||||
|
|
||||||
[:& interaction {:shape shape
|
[:& interaction {:shape shape
|
||||||
:interactions interactions
|
:interactions interactions
|
||||||
|
@ -393,20 +387,6 @@
|
||||||
(let [shape (unchecked-get props "shape")
|
(let [shape (unchecked-get props "shape")
|
||||||
frame (unchecked-get props "frame")
|
frame (unchecked-get props "frame")
|
||||||
|
|
||||||
;; TODO: this watch of scroll position is killing
|
|
||||||
;; performance of the viewer.
|
|
||||||
scroll (mf/use-ctx ctx/current-scroll)
|
|
||||||
zoom (mf/use-ctx ctx/current-zoom)
|
|
||||||
|
|
||||||
fixed? (mf/with-memo [shape objects]
|
|
||||||
(->> (cph/get-parent-ids objects (:id shape))
|
|
||||||
(map (d/getf objects))
|
|
||||||
(concat [shape])
|
|
||||||
(some :fixed-scroll)))
|
|
||||||
|
|
||||||
delta {:x (/ (:scroll-left scroll) zoom)
|
|
||||||
:y (/ (:scroll-top scroll) zoom)}
|
|
||||||
|
|
||||||
group-container
|
group-container
|
||||||
(mf/with-memo [objects]
|
(mf/with-memo [objects]
|
||||||
(group-container-factory objects))
|
(group-container-factory objects))
|
||||||
|
@ -426,8 +406,7 @@
|
||||||
]
|
]
|
||||||
(when (and shape (not (:hidden shape)))
|
(when (and shape (not (:hidden shape)))
|
||||||
(let [shape (-> (gsh/transform-shape shape)
|
(let [shape (-> (gsh/transform-shape shape)
|
||||||
(gsh/translate-to-frame frame)
|
(gsh/translate-to-frame frame))
|
||||||
(cond-> fixed? (gsh/move delta)))
|
|
||||||
|
|
||||||
opts #js {:shape shape
|
opts #js {:shape shape
|
||||||
:objects objects}]
|
:objects objects}]
|
||||||
|
@ -438,6 +417,6 @@
|
||||||
:path [:> path-wrapper opts]
|
:path [:> path-wrapper opts]
|
||||||
:image [:> image-wrapper opts]
|
:image [:> image-wrapper opts]
|
||||||
:circle [:> circle-wrapper opts]
|
:circle [:> circle-wrapper opts]
|
||||||
:group [:> group-container {:shape shape :frame frame :objects objects :fixed? fixed? :delta delta}]
|
:group [:> group-container {:shape shape :frame frame :objects objects}]
|
||||||
:bool [:> bool-container {:shape shape :frame frame :objects objects}]
|
:bool [:> bool-container {:shape shape :frame frame :objects objects}]
|
||||||
:svg-raw [:> svg-raw-container {:shape shape :frame frame :objects objects}])))))))
|
:svg-raw [:> svg-raw-container {:shape shape :frame frame :objects objects}])))))))
|
||||||
|
|
Loading…
Add table
Reference in a new issue