mirror of
https://github.com/penpot/penpot.git
synced 2025-05-29 04:06:11 +02:00
Merge pull request #6526 from penpot/superalex-improve-zoom-performance-and-behaviour
🐛 Fix zoom performance and behaviour
This commit is contained in:
commit
d54a7d0401
4 changed files with 60 additions and 30 deletions
|
@ -181,6 +181,18 @@ export function set_parent(id) {
|
||||||
Module._set_parent(...buffer);
|
Module._set_parent(...buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function debounce(fn, delay) {
|
||||||
|
let timeout;
|
||||||
|
return (...args) => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(() => fn(...args), delay);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const debouncedRender = debounce(() => {
|
||||||
|
Module._render(Date.now());
|
||||||
|
}, 100);
|
||||||
|
|
||||||
export function setupInteraction(canvas) {
|
export function setupInteraction(canvas) {
|
||||||
canvas.addEventListener("wheel", (e) => {
|
canvas.addEventListener("wheel", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -191,7 +203,8 @@ export function setupInteraction(canvas) {
|
||||||
offsetX -= (mouseX - offsetX) * (zoomFactor - 1);
|
offsetX -= (mouseX - offsetX) * (zoomFactor - 1);
|
||||||
offsetY -= (mouseY - offsetY) * (zoomFactor - 1);
|
offsetY -= (mouseY - offsetY) * (zoomFactor - 1);
|
||||||
Module._set_view(scale, offsetX, offsetY);
|
Module._set_view(scale, offsetX, offsetY);
|
||||||
Module._render(Date.now());
|
Module._render_from_cache();
|
||||||
|
debouncedRender();
|
||||||
});
|
});
|
||||||
|
|
||||||
canvas.addEventListener("mousedown", (e) => {
|
canvas.addEventListener("mousedown", (e) => {
|
||||||
|
@ -209,7 +222,8 @@ export function setupInteraction(canvas) {
|
||||||
lastX = e.offsetX;
|
lastX = e.offsetX;
|
||||||
lastY = e.offsetY;
|
lastY = e.offsetY;
|
||||||
Module._set_view(scale, offsetX, offsetY);
|
Module._set_view(scale, offsetX, offsetY);
|
||||||
Module._render(Date.now());
|
Module._render_from_cache();
|
||||||
|
debouncedRender();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
[app.render-wasm.serializers.fills :as sr-fills]
|
[app.render-wasm.serializers.fills :as sr-fills]
|
||||||
[app.render-wasm.wasm :as wasm]
|
[app.render-wasm.wasm :as wasm]
|
||||||
[app.util.debug :as dbg]
|
[app.util.debug :as dbg]
|
||||||
|
[app.util.functions :as fns]
|
||||||
[app.util.http :as http]
|
[app.util.http :as http]
|
||||||
[app.util.perf :as uperf]
|
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[promesa.core :as p]
|
[promesa.core :as p]
|
||||||
|
@ -101,6 +101,8 @@
|
||||||
(h/call wasm/internal-module "_render" timestamp)
|
(h/call wasm/internal-module "_render" timestamp)
|
||||||
(set! wasm/internal-frame-id nil))
|
(set! wasm/internal-frame-id nil))
|
||||||
|
|
||||||
|
(def debounce-render (fns/debounce render 100))
|
||||||
|
|
||||||
(defn cancel-render
|
(defn cancel-render
|
||||||
[_]
|
[_]
|
||||||
(when wasm/internal-frame-id
|
(when wasm/internal-frame-id
|
||||||
|
@ -662,7 +664,8 @@
|
||||||
(defn set-view-box
|
(defn set-view-box
|
||||||
[zoom vbox]
|
[zoom vbox]
|
||||||
(h/call wasm/internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox)))
|
(h/call wasm/internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox)))
|
||||||
(render (uperf/now)))
|
(h/call wasm/internal-module "_render_from_cache")
|
||||||
|
(debounce-render))
|
||||||
|
|
||||||
(defn clear-drawing-cache []
|
(defn clear-drawing-cache []
|
||||||
(h/call wasm/internal-module "_clear_drawing_cache"))
|
(h/call wasm/internal-module "_clear_drawing_cache"))
|
||||||
|
|
|
@ -91,9 +91,19 @@ pub extern "C" fn set_canvas_background(raw_color: u32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn render(timestamp: i32) {
|
pub extern "C" fn render(_: i32) {
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
state.start_render_loop(timestamp).expect("Error rendering");
|
state
|
||||||
|
.start_render_loop(performance::get_time())
|
||||||
|
.expect("Error rendering");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn render_from_cache(_: i32) {
|
||||||
|
with_state!(state, {
|
||||||
|
let render_state = state.render_state();
|
||||||
|
render_state.render_from_cache();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,17 +147,16 @@ pub extern "C" fn resize_viewbox(width: i32, height: i32) {
|
||||||
pub extern "C" fn set_view(zoom: f32, x: f32, y: f32) {
|
pub extern "C" fn set_view(zoom: f32, x: f32, y: f32) {
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
let render_state = state.render_state();
|
let render_state = state.render_state();
|
||||||
let zoom_changed = zoom != render_state.viewbox.zoom;
|
|
||||||
render_state.viewbox.set_all(zoom, x, y);
|
render_state.viewbox.set_all(zoom, x, y);
|
||||||
if zoom_changed {
|
with_state!(state, {
|
||||||
with_state!(state, {
|
// We can have renders in progress
|
||||||
if state.render_state.options.is_profile_rebuild_tiles() {
|
state.render_state.cancel_animation_frame();
|
||||||
state.rebuild_tiles();
|
if state.render_state.options.is_profile_rebuild_tiles() {
|
||||||
} else {
|
state.rebuild_tiles();
|
||||||
state.rebuild_tiles_shallow();
|
} else {
|
||||||
}
|
state.rebuild_tiles_shallow();
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -494,8 +494,16 @@ impl RenderState {
|
||||||
.update_render_context(self.render_area, self.get_scale());
|
.update_render_context(self.render_area, self.get_scale());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_from_cache(&mut self) {
|
pub fn cancel_animation_frame(&mut self) {
|
||||||
let scale = self.get_scale();
|
if self.render_in_progress {
|
||||||
|
if let Some(frame_id) = self.render_request_id {
|
||||||
|
wapi::cancel_animation_frame!(frame_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_from_cache(&mut self) {
|
||||||
|
let scale = self.get_cached_scale();
|
||||||
if let Some(snapshot) = &self.cached_target_snapshot {
|
if let Some(snapshot) = &self.cached_target_snapshot {
|
||||||
let canvas = self.surfaces.canvas(SurfaceId::Target);
|
let canvas = self.surfaces.canvas(SurfaceId::Target);
|
||||||
canvas.save();
|
canvas.save();
|
||||||
|
@ -525,6 +533,7 @@ impl RenderState {
|
||||||
canvas.clear(self.background_color);
|
canvas.clear(self.background_color);
|
||||||
canvas.draw_image(snapshot, (0, 0), Some(&skia::Paint::default()));
|
canvas.draw_image(snapshot, (0, 0), Some(&skia::Paint::default()));
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
|
self.flush_and_submit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,19 +544,12 @@ impl RenderState {
|
||||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||||
timestamp: i32,
|
timestamp: i32,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
if self.render_in_progress {
|
let scale = self.get_scale();
|
||||||
if let Some(frame_id) = self.render_request_id {
|
self.tile_viewbox.update(self.viewbox, scale);
|
||||||
wapi::cancel_animation_frame!(frame_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
performance::begin_measure!("render");
|
performance::begin_measure!("render");
|
||||||
performance::begin_measure!("start_render_loop");
|
performance::begin_measure!("start_render_loop");
|
||||||
|
|
||||||
// If we have cached data let's do a fast render from it
|
|
||||||
self.render_from_cache();
|
|
||||||
|
|
||||||
let scale = self.get_scale();
|
|
||||||
self.reset_canvas();
|
self.reset_canvas();
|
||||||
self.surfaces.apply_mut(
|
self.surfaces.apply_mut(
|
||||||
&[
|
&[
|
||||||
|
@ -601,9 +603,7 @@ impl RenderState {
|
||||||
self.flush_and_submit();
|
self.flush_and_submit();
|
||||||
|
|
||||||
if self.render_in_progress {
|
if self.render_in_progress {
|
||||||
if let Some(frame_id) = self.render_request_id {
|
self.cancel_animation_frame();
|
||||||
wapi::cancel_animation_frame!(frame_id);
|
|
||||||
}
|
|
||||||
self.render_request_id = Some(wapi::request_animation_frame!());
|
self.render_request_id = Some(wapi::request_animation_frame!());
|
||||||
} else {
|
} else {
|
||||||
performance::end_measure!("render");
|
performance::end_measure!("render");
|
||||||
|
@ -1041,4 +1041,8 @@ impl RenderState {
|
||||||
pub fn get_scale(&self) -> f32 {
|
pub fn get_scale(&self) -> f32 {
|
||||||
self.viewbox.zoom() * self.options.dpr()
|
self.viewbox.zoom() * self.options.dpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_cached_scale(&self) -> f32 {
|
||||||
|
self.cached_viewbox.zoom() * self.options.dpr()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue