diff --git a/packages/core/src/canvas/view/CanvasView.ts b/packages/core/src/canvas/view/CanvasView.ts index a0f3f5a883..170c1a6d72 100644 --- a/packages/core/src/canvas/view/CanvasView.ts +++ b/packages/core/src/canvas/view/CanvasView.ts @@ -38,6 +38,7 @@ export interface MarginPaddingOffsets { export type ElementPosOpts = { avoidFrameOffset?: boolean; avoidFrameZoom?: boolean; + avoidAbsolute?: boolean; noScroll?: boolean; }; @@ -345,7 +346,7 @@ export default class CanvasView extends ModuleView { */ offset(el?: HTMLElement, opts: ElementPosOpts = {}) { const { noScroll } = opts; - const rect = getElRect(el); + const rect = getElRect(el, opts); const scroll = noScroll ? { x: 0, y: 0 } : getDocumentScroll(el); return { diff --git a/packages/core/src/utils/Resizer.ts b/packages/core/src/utils/Resizer.ts index 3b52f7cc26..d643453222 100644 --- a/packages/core/src/utils/Resizer.ts +++ b/packages/core/src/utils/Resizer.ts @@ -472,7 +472,7 @@ export default class Resizer { const config = this.opts || {}; const mouseFetch = this.mousePosFetcher; const attrName = 'data-' + config.prefix + 'handler'; - const rect = this.getElementPos(el!, { avoidFrameZoom: true, avoidFrameOffset: true }); + const rect = this.getElementPos(el!, { avoidFrameZoom: true, avoidFrameOffset: true, avoidAbsolute: true }); const parentRect = this.getElementPos(parentEl!); const target = e.target as HTMLElement; this.handlerAttr = target.getAttribute(attrName)!; diff --git a/packages/core/src/utils/dom.ts b/packages/core/src/utils/dom.ts index cea444ad97..4479b5194c 100644 --- a/packages/core/src/utils/dom.ts +++ b/packages/core/src/utils/dom.ts @@ -1,5 +1,6 @@ import { each, isArray, isString, isUndefined } from 'underscore'; import { ObjectAny } from '../common'; +import { ElementPosOpts } from '../canvas/view/CanvasView'; type vNode = { tag?: string; @@ -157,7 +158,7 @@ export const isTaggableNode = (el?: Node) => el && !isTextNode(el) && !isComment * @param el * @returns {DOMRect} */ -export const getElRect = (el?: Element) => { +export const getElRect = (el?: Element, opts: ElementPosOpts = {}) => { const def = { top: 0, left: 0, @@ -174,6 +175,22 @@ export const getElRect = (el?: Element) => { range.detach(); } + const { top, left, width, height } = el.getBoundingClientRect ? el.getBoundingClientRect() : def; + const rect = { + top, + left, + width, + height, + }; + + const parentEl = el.parentElement; + const style = parentEl ? getComputedStyle(parentEl) : { position: '' }; + if (style.position === 'absolute' && opts.avoidAbsolute) { + rect.top = rect.top - (parentEl?.offsetTop || 0) - 2; + rect.left = rect.left - (parentEl?.offsetLeft || 0) - 2; + return rect; + } + return rectText || (el.getBoundingClientRect ? el.getBoundingClientRect() : def); };