Browse Source

Fix canvas scroll on component select from layers. Closes #5342

pull/5358/head
Artur Arseniev 2 years ago
parent
commit
d9c5ee9a7b
  1. 4
      src/canvas/types.ts
  2. 5
      src/canvas/view/CanvasView.ts
  3. 47
      src/dom_components/view/ComponentView.ts

4
src/canvas/types.ts

@ -6,7 +6,9 @@ export interface ToWorldOption {
toWorld?: boolean;
}
export interface GetBoxRectOptions extends ToScreenOption {}
export interface GetBoxRectOptions extends ToScreenOption {
local?: boolean;
}
/**{START_EVENTS}*/
export enum CanvasEvents {

5
src/canvas/view/CanvasView.ts

@ -386,6 +386,11 @@ export default class CanvasView extends ModuleView<Canvas> {
height,
};
if (opts.local) {
boxRect.x = left;
boxRect.y = top;
}
return opts.toScreen ? this.getRectToScreen(boxRect) : boxRect;
}

47
src/dom_components/view/ComponentView.ts

@ -16,13 +16,6 @@ import ComponentsView from './ComponentsView';
type ClbObj = ReturnType<ComponentView['_clbObj']>;
interface Rect {
top?: number;
left?: number;
bottom?: number;
right?: number;
}
export interface IComponentView extends ExtractMethods<ComponentView> {}
export default class ComponentView extends View</**
@ -433,7 +426,7 @@ Component> {
* have to take in account offsetParent
*/
getOffsetRect() {
const rect: Rect = {};
const rect = { top: 0, left: 0, bottom: 0, right: 0 };
const target = this.el;
let gtop = 0;
let gleft = 0;
@ -457,32 +450,38 @@ Component> {
return rect;
}
isInViewport({ rect }: { rect?: Rect } = {}) {
const { el } = this;
const elDoc = el.ownerDocument;
const { body } = elDoc;
const frameElement = elDoc.defaultView?.frameElement as HTMLIFrameElement;
const { top, left } = rect || this.getOffsetRect();
const frame = this.frameView.getOffsetRect();
isInViewport() {
const { el, em, frameView } = this;
const canvasView = em.Canvas.getCanvasView();
const elRect = canvasView.getElBoxRect(el, { local: true });
const frameEl = frameView.el;
const frameH = frameEl.clientHeight;
const frameW = frameEl.clientWidth;
const elTop = elRect.y;
const elRight = elRect.x;
const elBottom = elTop + elRect.height;
const elLeft = elRight + elRect.width;
const isTopInside = elTop >= 0 && elTop < frameH;
const isBottomInside = elBottom > 0 && elBottom < frameH;
const isLeftInside = elLeft >= 0 && elLeft < frameW;
const isRightInside = elRight > 0 && elRight <= frameW;
const partiallyIn = (isTopInside || isBottomInside) && (isLeftInside || isRightInside);
return (
top! >= frame.scrollTop &&
left! >= frame.scrollLeft &&
top! <= frame.scrollBottom &&
left! <= frameElement?.offsetWidth + body.scrollLeft
);
return partiallyIn;
}
scrollIntoView(opts: { force?: boolean } & ScrollIntoViewOptions = {}) {
const rect = this.getOffsetRect();
const isInViewport = this.isInViewport({ rect });
const isInViewport = this.isInViewport();
if (!isInViewport || opts.force) {
const { el } = this;
// PATCH: scrollIntoView won't work with multiple requests from iframes
if (opts.behavior !== 'smooth') {
el.ownerDocument.defaultView?.scrollTo(0, rect.top!);
const rect = this.getOffsetRect();
el.ownerDocument.defaultView?.scrollTo(0, rect.top);
} else {
el.scrollIntoView({
behavior: 'smooth',

Loading…
Cancel
Save