Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scrollable canvas feature #6395

Merged
merged 9 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/core/src/canvas/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ export interface CanvasConfig {
* Experimental: enable infinite canvas.
*/
infiniteCanvas?: boolean;

/**
* Enables the scrollable canvas feature.
*
* When this feature flag is set to `true`, the canvas element
* will have its `overflow` style set to `auto`, allowing users to scroll
* the canvas content if it exceeds the visible area. This is useful for
* handling large diagrams or zoomed-in views where parts of the content
* are initially hidden. If `false`, the canvas will use default overflow (typically hidden).
*
* @default false
*/
scrollableCanvas?: boolean;
}

const config: () => CanvasConfig = () => ({
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/canvas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,12 @@ export default class CanvasModule extends Module<CanvasConfig> {
*/
getMouseRelativeCanvas(ev: MouseEvent | { clientX: number; clientY: number }, opts: any) {
const zoom = this.getZoomDecimal();
const { top = 0, left = 0 } = this.getCanvasView().getPosition(opts) ?? {};
const canvasPos = this.getCanvasView().getPosition(opts) ?? { top: 0, left: 0 };
const canvasScroll = this.getCanvasView().getCanvasScroll();
const { top, left } = {
top: canvasPos.top + canvasScroll.scrollTop,
left: canvasPos.left + canvasScroll.scrollLeft,
};

return {
y: ev.clientY * zoom + top,
Expand Down
21 changes: 21 additions & 0 deletions packages/core/src/canvas/view/CanvasView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ export default class CanvasView extends ModuleView<Canvas> {
const frEl = winEl ? (winEl.frameElement as HTMLElement) : frame;
this.frmOff = this.offset(frEl || frame);
}

return this.frmOff;
}

Expand Down Expand Up @@ -562,6 +563,23 @@ export default class CanvasView extends ModuleView<Canvas> {
};
}

/**
* Returns the scroll position of the canvas.
*
* If the canvas is scrollable, returns the current `scrollTop` and `scrollLeft` values.
* Otherwise, returns an object with `scrollTop` and `scrollLeft` both set to 0.
*
* @returns An object containing the vertical and horizontal scroll positions.
*/
getCanvasScroll(): { scrollTop: number; scrollLeft: number } {
return this.config.scrollableCanvas
? {
scrollTop: this.el.scrollTop,
scrollLeft: this.el.scrollLeft,
}
: { scrollTop: 0, scrollLeft: 0 };
}

/**
* Update javascript of a specific component passed by its View
* @param {ModuleView} view Component's View
Expand Down Expand Up @@ -672,6 +690,9 @@ export default class CanvasView extends ModuleView<Canvas> {
this.spotsEl = el.querySelector('[data-spots]')!;
this.cvStyle = el.querySelector('[data-canvas-style]')!;
this.el.className = getUiClass(em, this.className);
if (config.scrollableCanvas === true) {
$el.css('overflow', 'auto');
}
this.ready = true;
this._renderFrames();

Expand Down