diff --git a/src/canvas/config/config.ts b/src/canvas/config/config.ts index 956bb0be2..f97109347 100644 --- a/src/canvas/config/config.ts +++ b/src/canvas/config/config.ts @@ -73,6 +73,11 @@ export interface CanvasConfig { allowExternalDrop?: boolean; customSpots?: boolean | Partial>; + + /** + * Experimental: enable infinite canvas. + */ + infiniteCanvas?: boolean; } const config: CanvasConfig = { diff --git a/src/canvas/view/CanvasView.ts b/src/canvas/view/CanvasView.ts index 53ae4cd37..55ec3665c 100644 --- a/src/canvas/view/CanvasView.ts +++ b/src/canvas/view/CanvasView.ts @@ -4,7 +4,16 @@ import { ModuleView } from '../../abstract'; import { BoxRect, Coordinates, ElementRect } from '../../common'; import Component from '../../dom_components/model/Component'; import ComponentView from '../../dom_components/view/ComponentView'; -import { createEl, getDocumentScroll, getElRect, getKeyChar, isTextNode, off, on } from '../../utils/dom'; +import { + createEl, + getDocumentScroll, + getElRect, + getKeyChar, + hasModifierKey, + isTextNode, + off, + on, +} from '../../utils/dom'; import { getComponentView, getElement, getUiClass } from '../../utils/mixins'; import Canvas from '../model/Canvas'; import Frame from '../model/Frame'; @@ -36,12 +45,6 @@ export interface FitViewportOptions { } export default class CanvasView extends ModuleView { - events() { - return { - wheel: 'onWheel', - }; - } - template() { const { pfx } = this; return ` @@ -82,7 +85,7 @@ export default class CanvasView extends ModuleView { constructor(model: Canvas) { super({ model }); - bindAll(this, 'clearOff', 'onKeyPress', 'onCanvasMove'); + bindAll(this, 'clearOff', 'onKeyPress', 'onCanvasMove', 'onWheel'); const { em, pfx } = this; this.className = `${pfx}canvas${!em.config.customUI ? ` ${pfx}canvas-bg` : ''}`; this.clsUnscale = `${pfx}unscale`; @@ -149,11 +152,11 @@ export default class CanvasView extends ModuleView { } toggleListeners(enable: boolean) { - const { el } = this; + const { el, config } = this; const fn = enable ? on : off; - // @ts-ignore fn(document, 'keypress', this.onKeyPress); fn(window, 'scroll resize', this.clearOff); + fn(el, 'wheel', this.onWheel, { passive: !config.infiniteCanvas }); // fn(el, 'mousemove dragover', this.onCanvasMove); } @@ -167,14 +170,23 @@ export default class CanvasView extends ModuleView { } } - onWheel(ev: KeyboardEvent) { - if ((ev.ctrlKey || ev.metaKey) && this.em.getConfig().multiFrames) { + onWheel(ev: WheelEvent) { + const { module, config } = this; + if (config.infiniteCanvas) { + const { deltaX, deltaY } = ev; + const zoom = module.getZoomDecimal(); + const isZooming = hasModifierKey(ev); this.preventDefault(ev); - const { model } = this; - //@ts-ignore this is potentially deprecated - const delta = Math.max(-1, Math.min(1, ev.wheelDelta || -ev.detail)); - const zoom = model.get('zoom'); - model.set('zoom', zoom + delta * 2); + + if (isZooming) { + const newZoom = zoom - deltaY * zoom * 0.01; + module.setZoom(newZoom * 100); + } else { + const diffX = deltaX / zoom; + const diffY = deltaY / zoom; + const coords = module.getCoords(); + module.setCoords(coords.x - diffX, coords.y - diffY); + } } } diff --git a/src/editor/config/config.ts b/src/editor/config/config.ts index d2411d3e3..1560006de 100644 --- a/src/editor/config/config.ts +++ b/src/editor/config/config.ts @@ -415,7 +415,6 @@ export interface EditorConfig { */ customUI?: boolean; el?: HTMLElement; - multiFrames?: boolean; /** * Color picker options. */ @@ -496,7 +495,6 @@ const config: EditorConfig = { traitManager: {}, textViewCode: 'Code', keepUnusedStyles: false, - multiFrames: false, customUI: false, }; diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 7faaf16ef..909ed0344 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -201,6 +201,10 @@ export const isEscKey = (ev: KeyboardEvent) => getKeyCode(ev) === 27; export const isEnterKey = (ev: KeyboardEvent) => getKeyCode(ev) === 13; +export const hasCtrlKey = (ev: WheelEvent) => ev.ctrlKey; + +export const hasModifierKey = (ev: WheelEvent) => hasCtrlKey(ev) || ev.metaKey; + export const on = ( el: EventTarget | EventTarget[], ev: string,