0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-10 09:08:31 -05:00

Merge pull request #2225 from penpot/superalex-viwer-performance-degradation-because-of-fixed-position

🎉 Improve viewer performance degradation because of fixed position
This commit is contained in:
Andrey Antukh 2022-09-14 08:30:53 +02:00 committed by GitHub
commit 8fa49eada8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 85 deletions

View file

@ -171,6 +171,20 @@
}
.viewport-container {
clip-path: inset(0 0 0 0);
grid-column: 1 / 1;
grid-row: 1 / 1;
.not-fixed {
position: absolute;
}
.fixed {
position: fixed;
pointer-events: none;
.frame-children g {
pointer-events: auto;
}
}
}

View file

@ -42,21 +42,13 @@
(if masked-group?
["g" (-> (obj/create)
(obj/set! "mask" (mask-url render-id mask)))]
[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?")]
[mf/Fragment nil])]
[:> clip-wrapper clip-props
[:> mask-wrapper mask-props
(when masked-group?
[:> render-mask #js {:mask mask
:objects objects
:delta delta
:fixed? fixed?}])
:objects objects}])
(for [item childs]
[:& shape-wrapper {:shape item

View file

@ -50,13 +50,7 @@
render-id (mf/use-ctx muc/render-id)
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)
(cond-> fixed? (gsh/move delta))
(:points))
mask-bb-rect (gsh/points->rect mask-bb)]

View file

@ -255,7 +255,6 @@
fullscreen? (mf/deref header/fullscreen-ref)
overlays (mf/deref current-overlays-ref)
scroll (mf/use-state nil)
orig-frame
(mf/with-memo [current-animations]
@ -309,11 +308,6 @@
size (dom/get-client-size viewer-section)]
(st/emit! (dv/set-viewport-size {:size size})))))
on-scroll
(mf/use-fn
(fn [event]
(reset! scroll (dom/get-target-scroll event))))
on-wheel
(mf/use-fn
(fn [event]
@ -354,12 +348,10 @@
(mf/with-effect []
(dom/set-html-theme-color clr/gray-50 "dark")
(let [key1 (events/listen js/window "click" on-click)
key2 (events/listen (mf/ref-val viewer-section-ref) "scroll" on-scroll #js {"passive" true})
key3 (events/listen (mf/ref-val viewer-section-ref) "wheel" on-wheel #js {"passive" false})]
key2 (events/listen (mf/ref-val viewer-section-ref) "wheel" on-wheel #js {"passive" false})]
(fn []
(events/unlistenByKey key1)
(events/unlistenByKey key2)
(events/unlistenByKey key3))))
(events/unlistenByKey key2))))
(mf/use-layout-effect
(fn []
@ -499,24 +491,24 @@
:index index
:viewer-pagination viewer-pagination}]
[:& (mf/provider ctx/current-scroll) {:value @scroll}
[:& (mf/provider ctx/current-zoom) {:value zoom}
[:& viewer-wrapper
{:wrapper-size wrapper-size
:orig-frame orig-frame
:orig-viewport-ref orig-viewport-ref
:orig-size orig-size
:page page
:file file
:users users
:current-viewport-ref current-viewport-ref
:size size
:frame frame
:interactions-mode interactions-mode
:overlays overlays
:zoom zoom
:section section
:index index}]]]))]]]))
[:& (mf/provider ctx/current-zoom) {:value zoom}
[:& viewer-wrapper
{:wrapper-size wrapper-size
:orig-frame orig-frame
:orig-viewport-ref orig-viewport-ref
:orig-size orig-size
:page page
:file file
:users users
:current-viewport-ref current-viewport-ref
:size size
:frame frame
:interactions-mode interactions-mode
:overlays overlays
:zoom zoom
:section section
:index index}]]))]]]))
;; --- Component: Viewer Page

View file

@ -189,7 +189,7 @@
(mf/defc render-frame-svg
[{:keys [page frame local 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
frame (get objects (:id frame))

View file

@ -12,6 +12,7 @@
[app.common.geom.point :as gpt]
[app.common.pages.helpers :as cph]
[app.common.types.page :as ctp]
[app.common.uuid :as uuid]
[app.main.data.comments :as dcm]
[app.main.data.viewer :as dv]
[app.main.refs :as refs]
@ -27,8 +28,8 @@
[rumext.alpha :as mf]))
(defn prepare-objects
[page frame size]
(let [objects (:objects page)
[frame size objects]
(let [
frame-id (:id frame)
modifier (-> (gpt/point (:x size) (:y size))
(gpt/negate)
@ -52,26 +53,60 @@
vbox (:vbox size)
objects (mf/with-memo [page frame size]
(prepare-objects page frame size))
fixed-ids (filter :fixed-scroll (vals (:objects page)))
wrapper (mf/with-memo [objects]
(shapes/frame-container-factory objects))
;; we have con consider the children if the fixed element is a group
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
frame (get objects (:id frame))
base (get objects (:id base))]
frame (get objects-not-fixed (:id frame))
base (get objects-not-fixed (:id base))]
[:& (mf/provider shapes/base-frame-ctx) {:value base}
[:& (mf/provider shapes/frame-offset-ctx) {:value offset}
[:svg {: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"}
[:& wrapper {:shape frame :view-box vbox}]]]]))
;; We have two different svgs for fixed and not fixed elements so we can emulate the sticky css attribute in svg
[:svg.not-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"}
[:& 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/wrap [mf/memo]

View file

@ -7,14 +7,12 @@
(ns app.main.ui.viewer.shapes
"The main container for a frame in viewer mode"
(:require
[app.common.data :as d]
[app.common.geom.shapes :as gsh]
[app.common.pages.helpers :as cph]
[app.common.types.shape.interactions :as ctsi]
[app.main.data.viewer :as dv]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.shapes.bool :as bool]
[app.main.ui.shapes.circle :as circle]
[app.main.ui.shapes.frame :as frame]
@ -223,8 +221,6 @@
childs (unchecked-get props "childs")
frame (unchecked-get props "frame")
objects (unchecked-get props "objects")
fixed? (unchecked-get props "fixed?")
delta (unchecked-get props "delta")
base-frame (mf/use-ctx base-frame-ctx)
frame-offset (mf/use-ctx frame-offset-ctx)
@ -269,9 +265,7 @@
:frame frame
:childs childs
:is-child-selected? true
:objects objects
:fixed? fixed?
:delta delta}]
:objects objects}]
[:& interaction {:shape shape
:interactions interactions
@ -393,20 +387,6 @@
(let [shape (unchecked-get props "shape")
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
(mf/with-memo [objects]
(group-container-factory objects))
@ -426,8 +406,7 @@
]
(when (and shape (not (:hidden shape)))
(let [shape (-> (gsh/transform-shape shape)
(gsh/translate-to-frame frame)
(cond-> fixed? (gsh/move delta)))
(gsh/translate-to-frame frame))
opts #js {:shape shape
:objects objects}]
@ -438,6 +417,6 @@
:path [:> path-wrapper opts]
:image [:> image-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}]
:svg-raw [:> svg-raw-container {:shape shape :frame frame :objects objects}])))))))