mirror of
https://github.com/penpot/penpot.git
synced 2025-05-19 20:56:11 +02:00
🐛 Improved zoom responsiveness
This commit is contained in:
parent
33e776fefe
commit
40de8781ef
2 changed files with 196 additions and 21 deletions
|
@ -21,12 +21,14 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.dom.dnd :as dnd]
|
[app.util.dom.dnd :as dnd]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
|
[app.util.normalize-wheel :as nw]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[app.util.timers :as timers]
|
[app.util.timers :as timers]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.alpha :as mf])
|
[rumext.alpha :as mf]))
|
||||||
(:import goog.events.WheelEvent))
|
|
||||||
|
(def scale-per-pixel -0.0057)
|
||||||
|
|
||||||
(defn on-mouse-down
|
(defn on-mouse-down
|
||||||
[{:keys [id blocked hidden type]} selected edition drawing-tool text-editing?
|
[{:keys [id blocked hidden type]} selected edition drawing-tool text-editing?
|
||||||
|
@ -377,32 +379,24 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [pt (->> (dom/get-client-position event)
|
(let [pt (->> (dom/get-client-position event)
|
||||||
(utils/translate-point-to-viewport viewport zoom))
|
(utils/translate-point-to-viewport viewport zoom))
|
||||||
|
|
||||||
|
norm-event ^js (nw/normalize-wheel event)
|
||||||
ctrl? (kbd/ctrl? event)
|
ctrl? (kbd/ctrl? event)
|
||||||
|
delta-y (.-pixelY norm-event)
|
||||||
|
delta-x (.-pixelX norm-event)]
|
||||||
|
|
||||||
delta-mode (.-deltaMode ^js event)
|
|
||||||
|
|
||||||
unit (cond
|
|
||||||
(= delta-mode WheelEvent.DeltaMode.PIXEL) 1
|
|
||||||
(= delta-mode WheelEvent.DeltaMode.LINE) 16
|
|
||||||
(= delta-mode WheelEvent.DeltaMode.PAGE) 100)
|
|
||||||
|
|
||||||
delta-y (-> (.-deltaY ^js event)
|
|
||||||
(* unit)
|
|
||||||
(/ zoom))
|
|
||||||
|
|
||||||
delta-x (-> (.-deltaX ^js event)
|
|
||||||
(* unit)
|
|
||||||
(/ zoom))]
|
|
||||||
(if (or ctrl? mod?)
|
(if (or ctrl? mod?)
|
||||||
(let [delta (* -1 (+ delta-y delta-x))
|
(let [delta-zoom (+ delta-y delta-x)
|
||||||
scale (-> (+ 1 (/ delta 100)) (mth/clamp 0.77 1.3))]
|
scale (+ 1 (mth/abs (* scale-per-pixel delta-zoom)))
|
||||||
|
scale (if (pos? delta-zoom) (/ 1 scale) scale)]
|
||||||
(st/emit! (dw/set-zoom pt scale)))
|
(st/emit! (dw/set-zoom pt scale)))
|
||||||
|
|
||||||
(if (and (not (cfg/check-platform? :macos))
|
(if (and (not (cfg/check-platform? :macos))
|
||||||
;; macos sends delta-x automatically, don't need to do it
|
;; macos sends delta-x automatically, don't need to do it
|
||||||
(kbd/shift? event))
|
(kbd/shift? event))
|
||||||
(st/emit! (dw/update-viewport-position {:x #(+ % delta-y)}))
|
(st/emit! (dw/update-viewport-position {:x #(+ % (/ delta-y zoom))}))
|
||||||
(st/emit! (dw/update-viewport-position {:x #(+ % delta-x)
|
(st/emit! (dw/update-viewport-position {:x #(+ % (/ delta-x zoom))
|
||||||
:y #(+ % delta-y)}))))))))))
|
:y #(+ % (/ delta-y zoom))}))))))))))
|
||||||
|
|
||||||
(defn on-drag-enter []
|
(defn on-drag-enter []
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
|
181
frontend/src/app/util/dom/normalize_wheel.js
Normal file
181
frontend/src/app/util/dom/normalize_wheel.js
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @providesModule normalizeWheel
|
||||||
|
* @typechecks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Adapted to google closure from:
|
||||||
|
https://raw.githubusercontent.com/facebookarchive/fixed-data-table/master/src/vendor_upstream/dom/normalizeWheel.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
goog.provide("app.util.normalize_wheel");
|
||||||
|
|
||||||
|
goog.scope(function() {
|
||||||
|
const self = app.util.normalize_wheel;
|
||||||
|
|
||||||
|
// const UserAgent_DEPRECATED = require('UserAgent_DEPRECATED');
|
||||||
|
|
||||||
|
// const isEventSupported = require('isEventSupported');
|
||||||
|
|
||||||
|
|
||||||
|
// Reasonable defaults
|
||||||
|
const PIXEL_STEP = 10;
|
||||||
|
const LINE_HEIGHT = 40;
|
||||||
|
const PAGE_HEIGHT = 800;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mouse wheel (and 2-finger trackpad) support on the web sucks. It is
|
||||||
|
* complicated, thus this doc is long and (hopefully) detailed enough to answer
|
||||||
|
* your questions.
|
||||||
|
*
|
||||||
|
* If you need to react to the mouse wheel in a predictable way, this code is
|
||||||
|
* like your bestest friend. * hugs *
|
||||||
|
*
|
||||||
|
* As of today, there are 4 DOM event types you can listen to:
|
||||||
|
*
|
||||||
|
* 'wheel' -- Chrome(31+), FF(17+), IE(9+)
|
||||||
|
* 'mousewheel' -- Chrome, IE(6+), Opera, Safari
|
||||||
|
* 'MozMousePixelScroll' -- FF(3.5 only!) (2010-2013) -- don't bother!
|
||||||
|
* 'DOMMouseScroll' -- FF(0.9.7+) since 2003
|
||||||
|
*
|
||||||
|
* So what to do? The is the best:
|
||||||
|
*
|
||||||
|
* normalizeWheel.getEventType();
|
||||||
|
*
|
||||||
|
* In your event callback, use this code to get sane interpretation of the
|
||||||
|
* deltas. This code will return an object with properties:
|
||||||
|
*
|
||||||
|
* spinX -- normalized spin speed (use for zoom) - x plane
|
||||||
|
* spinY -- " - y plane
|
||||||
|
* pixelX -- normalized distance (to pixels) - x plane
|
||||||
|
* pixelY -- " - y plane
|
||||||
|
*
|
||||||
|
* Wheel values are provided by the browser assuming you are using the wheel to
|
||||||
|
* scroll a web page by a number of lines or pixels (or pages). Values can vary
|
||||||
|
* significantly on different platforms and browsers, forgetting that you can
|
||||||
|
* scroll at different speeds. Some devices (like trackpads) emit more events
|
||||||
|
* at smaller increments with fine granularity, and some emit massive jumps with
|
||||||
|
* linear speed or acceleration.
|
||||||
|
*
|
||||||
|
* This code does its best to normalize the deltas for you:
|
||||||
|
*
|
||||||
|
* - spin is trying to normalize how far the wheel was spun (or trackpad
|
||||||
|
* dragged). This is super useful for zoom support where you want to
|
||||||
|
* throw away the chunky scroll steps on the PC and make those equal to
|
||||||
|
* the slow and smooth tiny steps on the Mac. Key data: This code tries to
|
||||||
|
* resolve a single slow step on a wheel to 1.
|
||||||
|
*
|
||||||
|
* - pixel is normalizing the desired scroll delta in pixel units. You'll
|
||||||
|
* get the crazy differences between browsers, but at least it'll be in
|
||||||
|
* pixels!
|
||||||
|
*
|
||||||
|
* - positive value indicates scrolling DOWN/RIGHT, negative UP/LEFT. This
|
||||||
|
* should translate to positive value zooming IN, negative zooming OUT.
|
||||||
|
* This matches the newer 'wheel' event.
|
||||||
|
*
|
||||||
|
* Why are there spinX, spinY (or pixels)?
|
||||||
|
*
|
||||||
|
* - spinX is a 2-finger side drag on the trackpad, and a shift + wheel turn
|
||||||
|
* with a mouse. It results in side-scrolling in the browser by default.
|
||||||
|
*
|
||||||
|
* - spinY is what you expect -- it's the classic axis of a mouse wheel.
|
||||||
|
*
|
||||||
|
* - I dropped spinZ/pixelZ. It is supported by the DOM 3 'wheel' event and
|
||||||
|
* probably is by browsers in conjunction with fancy 3D controllers .. but
|
||||||
|
* you know.
|
||||||
|
*
|
||||||
|
* Implementation info:
|
||||||
|
*
|
||||||
|
* Examples of 'wheel' event if you scroll slowly (down) by one step with an
|
||||||
|
* average mouse:
|
||||||
|
*
|
||||||
|
* OS X + Chrome (mouse) - 4 pixel delta (wheelDelta -120)
|
||||||
|
* OS X + Safari (mouse) - N/A pixel delta (wheelDelta -12)
|
||||||
|
* OS X + Firefox (mouse) - 0.1 line delta (wheelDelta N/A)
|
||||||
|
* Win8 + Chrome (mouse) - 100 pixel delta (wheelDelta -120)
|
||||||
|
* Win8 + Firefox (mouse) - 3 line delta (wheelDelta -120)
|
||||||
|
*
|
||||||
|
* On the trackpad:
|
||||||
|
*
|
||||||
|
* OS X + Chrome (trackpad) - 2 pixel delta (wheelDelta -6)
|
||||||
|
* OS X + Firefox (trackpad) - 1 pixel delta (wheelDelta N/A)
|
||||||
|
*
|
||||||
|
* On other/older browsers.. it's more complicated as there can be multiple and
|
||||||
|
* also missing delta values.
|
||||||
|
*
|
||||||
|
* The 'wheel' event is more standard:
|
||||||
|
*
|
||||||
|
* http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents
|
||||||
|
*
|
||||||
|
* The basics is that it includes a unit, deltaMode (pixels, lines, pages), and
|
||||||
|
* deltaX, deltaY and deltaZ. Some browsers provide other values to maintain
|
||||||
|
* backward compatibility with older events. Those other values help us
|
||||||
|
* better normalize spin speed. Example of what the browsers provide:
|
||||||
|
*
|
||||||
|
* | event.wheelDelta | event.detail
|
||||||
|
* ------------------+------------------+--------------
|
||||||
|
* Safari v5/OS X | -120 | 0
|
||||||
|
* Safari v5/Win7 | -120 | 0
|
||||||
|
* Chrome v17/OS X | -120 | 0
|
||||||
|
* Chrome v17/Win7 | -120 | 0
|
||||||
|
* IE9/Win7 | -120 | undefined
|
||||||
|
* Firefox v4/OS X | undefined | 1
|
||||||
|
* Firefox v4/Win7 | undefined | 3
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function normalizeWheel(/*object*/ event) /*object*/ {
|
||||||
|
var sX = 0, sY = 0, // spinX, spinY
|
||||||
|
pX = 0, pY = 0; // pixelX, pixelY
|
||||||
|
|
||||||
|
// Legacy
|
||||||
|
if ('detail' in event) { sY = event.detail; }
|
||||||
|
if ('wheelDelta' in event) { sY = -event.wheelDelta / 120; }
|
||||||
|
if ('wheelDeltaY' in event) { sY = -event.wheelDeltaY / 120; }
|
||||||
|
if ('wheelDeltaX' in event) { sX = -event.wheelDeltaX / 120; }
|
||||||
|
|
||||||
|
// side scrolling on FF with DOMMouseScroll
|
||||||
|
if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
|
||||||
|
sX = sY;
|
||||||
|
sY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pX = sX * PIXEL_STEP;
|
||||||
|
pY = sY * PIXEL_STEP;
|
||||||
|
|
||||||
|
if ('deltaY' in event) { pY = event.deltaY; }
|
||||||
|
if ('deltaX' in event) { pX = event.deltaX; }
|
||||||
|
|
||||||
|
if ((pX || pY) && event.deltaMode) {
|
||||||
|
if (event.deltaMode == 1) { // delta in LINE units
|
||||||
|
pX *= LINE_HEIGHT;
|
||||||
|
pY *= LINE_HEIGHT;
|
||||||
|
} else { // delta in PAGE units
|
||||||
|
pX *= PAGE_HEIGHT;
|
||||||
|
pY *= PAGE_HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall-back if spin cannot be determined
|
||||||
|
if (pX && !sX) { sX = (pX < 1) ? -1 : 1; }
|
||||||
|
if (pY && !sY) { sY = (pY < 1) ? -1 : 1; }
|
||||||
|
|
||||||
|
return { spinX : sX,
|
||||||
|
spinY : sY,
|
||||||
|
pixelX : pX,
|
||||||
|
pixelY : pY };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
self.normalize_wheel = normalizeWheel;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue