diff --git a/src/canvas/index.ts b/src/canvas/index.ts index 5eec3359c..395e20123 100644 --- a/src/canvas/index.ts +++ b/src/canvas/index.ts @@ -40,7 +40,7 @@ import Canvas from './model/Canvas'; import CanvasSpot, { CanvasSpotBuiltInTypes, CanvasSpotProps } from './model/CanvasSpot'; import CanvasSpots from './model/CanvasSpots'; import Frame from './model/Frame'; -import { CanvasEvents, ToWorldOption } from './types'; +import { CanvasEvents, CanvasRefreshOptions, ToWorldOption } from './types'; import CanvasView, { FitViewportOptions } from './view/CanvasView'; import FrameView from './view/FrameView'; @@ -834,6 +834,24 @@ export default class CanvasModule extends Module { return this.canvasView?.getRectToScreen(boxRect); } + /** + * Update canvas for spots/tools positioning. + * @param {Object} [opts] Options. + * @param {Object} [opts.spots=false] Update the position of spots. + */ + refresh(opts: CanvasRefreshOptions = {}) { + const { em, events, canvasView } = this; + canvasView?.clearOff(); + + if (opts.spots || opts.all) { + this.refreshSpots(); + em.trigger('canvas:updateTools'); // this should be deprecated + } + + em.set('canvasOffset', this.getOffset()); // this should be deprecated + em.trigger(events.refresh, opts); + } + refreshSpots() { this.spots.refresh(); } diff --git a/src/canvas/types.ts b/src/canvas/types.ts index 7f9d31623..51190d4ff 100644 --- a/src/canvas/types.ts +++ b/src/canvas/types.ts @@ -10,6 +10,14 @@ export interface GetBoxRectOptions extends ToScreenOption { local?: boolean; } +export interface CanvasRefreshOptions { + /** + * Refresh canvas spots. + */ + spots?: boolean; + all?: boolean; +} + /**{START_EVENTS}*/ export enum CanvasEvents { /** @@ -101,6 +109,16 @@ export enum CanvasEvents { */ pointer = 'canvas:pointer', + /** + * @event `canvas:refresh` Canvas was refreshed to update elements on top, + * like spots/tools (eg. via `editor.Canvas.refresh()` or on frame resize). + * @example + * editor.on('canvas:refresh', (canvasRefreshOptions) => { + * console.log('Canvas refreshed with options:', canvasRefreshOptions); + * }); + */ + refresh = 'canvas:refresh', + /** * @event `canvas:frame:load` Frame loaded in canvas. * The event is triggered right after iframe's `onload`. diff --git a/src/canvas/view/CanvasView.ts b/src/canvas/view/CanvasView.ts index 6cc3be6ca..8c2d4b183 100644 --- a/src/canvas/view/CanvasView.ts +++ b/src/canvas/view/CanvasView.ts @@ -95,7 +95,7 @@ export default class CanvasView extends ModuleView { this.className = `${pfx}canvas ${ppfx}no-touch-actions${!em.config.customUI ? ` ${pfx}canvas-bg` : ''}`; this.clsUnscale = `${pfx}unscale`; this._initFrames(); - this.listenTo(em, 'change:canvasOffset', this.clearOff); + this.listenTo(em, events.refresh, this.clearOff); this.listenTo(em, 'component:selected', this.checkSelected); this.listenTo(em, `${events.coords} ${events.zoom}`, this.updateFrames); this.listenTo(model, 'change:frames', this._onFramesUpdate); diff --git a/src/commands/view/Fullscreen.ts b/src/commands/view/Fullscreen.ts index d8ec3b85e..105a065d2 100644 --- a/src/commands/view/Fullscreen.ts +++ b/src/commands/view/Fullscreen.ts @@ -72,12 +72,10 @@ export default { const pfx = this.enable(targetEl || editor.getContainer()); this.fsChanged = this.fsChanged.bind(this, pfx); document.addEventListener(pfx + 'fullscreenchange', this.fsChanged); - editor.trigger('change:canvasOffset'); }, stop(editor, sender) { if (sender && sender.set) sender.set('active', false); this.disable(); - if (editor) editor.trigger('change:canvasOffset'); }, } as CommandObject<{ target?: HTMLElement | string }, { [k: string]: any }>; diff --git a/src/commands/view/SelectComponent.ts b/src/commands/view/SelectComponent.ts index 33e5d3189..8b500140c 100644 --- a/src/commands/view/SelectComponent.ts +++ b/src/commands/view/SelectComponent.ts @@ -91,9 +91,9 @@ export default { em[method]('change:componentHovered', this.onHovered, this); em[method]('component:resize styleable:change component:input', this.updateGlobalPos, this); em[method]('component:update:toolbar', this._upToolbar, this); - em[method]('change:canvasOffset', this.updateAttached, this); em[method]('frame:updated', this.onFrameUpdated, this); em[method]('canvas:updateTools', this.onFrameUpdated, this); + em[method](em.Canvas.events.refresh, this.updateAttached, this); em.Canvas.getFrames().forEach(frame => { const { view } = frame; const win = view?.getWindow(); @@ -580,7 +580,7 @@ export default { }, onFrameResize() { - this.canvas.refreshSpots(); + this.canvas.refresh({ all: true }); }, updateTools() { diff --git a/src/dom_components/view/ComponentImageView.ts b/src/dom_components/view/ComponentImageView.ts index 595d0c70b..ee5aab523 100644 --- a/src/dom_components/view/ComponentImageView.ts +++ b/src/dom_components/view/ComponentImageView.ts @@ -103,7 +103,7 @@ export default class ComponentImageView { avoidContainerUpdate: true, prefix: editor.getConfig().stylePrefix, onEnd() { - em && em.trigger('change:canvasOffset'); + em.Canvas.refresh({ all: true }); }, posFetcher: (el: HTMLElement, { target }: any) => { const style = el.style as any; diff --git a/src/rich_text_editor/index.ts b/src/rich_text_editor/index.ts index 007a8d6f4..54cd110c3 100644 --- a/src/rich_text_editor/index.ts +++ b/src/rich_text_editor/index.ts @@ -46,10 +46,11 @@ import { createEl, cx, on, removeEl } from '../utils/dom'; import { hasWin, isDef } from '../utils/mixins'; import defaults, { CustomRTE, RichTextEditorConfig } from './config/config'; import RichTextEditor, { RichTextEditorAction } from './model/RichTextEditor'; +import CanvasEvents from '../canvas/types'; export type RichTextEditorEvent = 'rte:enable' | 'rte:disable' | 'rte:custom'; -const eventsUp = 'change:canvasOffset frame:scroll component:update'; +const eventsUp = `${CanvasEvents.refresh} frame:scroll component:update`; export const evEnable = 'rte:enable'; export const evDisable = 'rte:disable'; diff --git a/src/undo_manager/index.ts b/src/undo_manager/index.ts index 1e289b784..2328cef42 100644 --- a/src/undo_manager/index.ts +++ b/src/undo_manager/index.ts @@ -133,7 +133,6 @@ export default class UndoManagerModule extends Module { - em.trigger('change:canvasOffset'); em.getSelectedAll().map(c => c.trigger('rerender:layer')); }); ['undo', 'redo'].forEach(ev => this.um.on(ev, () => em.trigger(ev))); diff --git a/src/utils/Sorter.ts b/src/utils/Sorter.ts index 6a2d7ccef..b87a14226 100644 --- a/src/utils/Sorter.ts +++ b/src/utils/Sorter.ts @@ -155,9 +155,10 @@ export default class Sorter extends View { this.canvasRelative = !!o.canvasRelative; this.selectOnEnd = !o.avoidSelectOnEnd; this.scale = o.scale; + const { em } = this; - if (this.em && this.em.on) { - this.em.on('change:canvasOffset', this.updateOffset); + if (em?.on) { + em.on(em.Canvas.events.refresh, this.updateOffset); this.updateOffset(); } }