Skip to content

Commit

Permalink
refactor(ui): compute size without using getBoundingClientRect
Browse files Browse the repository at this point in the history
When the element contains transition, using `getBoundingClientRect` will often not get the original size.
  • Loading branch information
xiejay97 committed Nov 18, 2022
1 parent a1de215 commit eec6be0
Show file tree
Hide file tree
Showing 19 changed files with 47 additions and 73 deletions.
5 changes: 3 additions & 2 deletions packages/platform/src/app/components/map/MapMarker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ export function AppMapMarker(props: AppMapMarkerProps): JSX.Element | null {
div.innerHTML = elRef.current.outerHTML;
div.style.cssText = 'position:fixed;top:-200vh;left:-200vw;';
document.body.appendChild(div);
const rect = div.firstElementChild!.getBoundingClientRect();
const width = (div.firstElementChild as HTMLElement).offsetWidth;
const height = (div.firstElementChild as HTMLElement).offsetHeight;
document.body.removeChild(div);

return new AMap.Pixel(-(rect.width / 2), -rect.height);
return new AMap.Pixel(-(width / 2), -height);
})()
: isArray(aOptions.offset)
? new AMap.Pixel(...aOptions.offset)
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/_date-input/DateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ReactDOM from 'react-dom';

import { useAsync, useEvent, useEventCallback, useForceUpdate, useForkRef, useImmer, useRefExtra, useResize } from '@react-devui/hooks';
import { CloseCircleFilled, SwapRightOutlined } from '@react-devui/icons';
import { checkNodeExist, getClassName, getOriginalSize, getVerticalSidePosition } from '@react-devui/utils';
import { checkNodeExist, getClassName, getVerticalSidePosition } from '@react-devui/utils';

import { dayjs } from '../../dayjs';
import { useDValue, useMaxIndex } from '../../hooks';
Expand Down Expand Up @@ -210,7 +210,7 @@ function DateInput(props: DDateInputProps, ref: React.ForwardedRef<DDateInputRef
const [transformOrigin, setTransformOrigin] = useState<string>();
const updatePosition = useEventCallback(() => {
if (visible && boxRef.current && popupRef.current) {
const { height } = getOriginalSize(popupRef.current);
const height = popupRef.current.offsetHeight;
const maxWidth = window.innerWidth - WINDOW_SPACE * 2;
const width = Math.min(popupRef.current.scrollWidth, maxWidth);
const { top, left, transformOrigin } = getVerticalSidePosition(
Expand Down
6 changes: 2 additions & 4 deletions packages/ui/src/components/_transition/CollapseTransition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ export function DCollapseTransition(props: DCollapseTransitionProps): JSX.Elemen
ref.current.style.width = 'auto';
ref.current.style.paddingLeft = getSizeStyle(dOriginalSize.padding?.[3]);
ref.current.style.paddingRight = getSizeStyle(dOriginalSize.padding?.[1]);
const { width } = ref.current.getBoundingClientRect();
dataRef.current.width = width;
dataRef.current.width = ref.current.offsetWidth;
ref.current.style.cssText = cssText;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
ref.current.offsetTop;
Expand All @@ -69,8 +68,7 @@ export function DCollapseTransition(props: DCollapseTransitionProps): JSX.Elemen
ref.current.style.height = 'auto';
ref.current.style.paddingTop = getSizeStyle(dOriginalSize.padding?.[0]);
ref.current.style.paddingBottom = getSizeStyle(dOriginalSize.padding?.[2]);
const { height } = ref.current.getBoundingClientRect();
dataRef.current.height = height;
dataRef.current.height = ref.current.offsetHeight;
ref.current.style.cssText = cssText;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
ref.current.offsetTop;
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/src/components/auto-complete/AutoComplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ReactDOM from 'react-dom';

import { useEvent, useEventCallback, useId, useRefExtra, useResize } from '@react-devui/hooks';
import { LoadingOutlined } from '@react-devui/icons';
import { findNested, getClassName, getOriginalSize, getVerticalSidePosition } from '@react-devui/utils';
import { findNested, getClassName, getVerticalSidePosition } from '@react-devui/utils';

import { useMaxIndex, useDValue } from '../../hooks';
import { cloneHTMLElement, registerComponentMate, TTANSITION_DURING_POPUP, WINDOW_SPACE } from '../../utils';
Expand Down Expand Up @@ -100,8 +100,8 @@ function AutoComplete<T extends DAutoCompleteItem>(
const [transformOrigin, setTransformOrigin] = useState<string>();
const updatePosition = useEventCallback(() => {
if (visible && boxRef.current && popupRef.current) {
const boxWidth = boxRef.current.getBoundingClientRect().width;
const { height } = getOriginalSize(popupRef.current);
const boxWidth = boxRef.current.offsetWidth;
const height = popupRef.current.offsetHeight;
const maxWidth = window.innerWidth - WINDOW_SPACE * 2;
const width = Math.min(Math.max(popupRef.current.scrollWidth, boxWidth), maxWidth);
const { top, left, transformOrigin } = getVerticalSidePosition(
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/cascader/Cascader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import React, { useCallback, useState, useMemo, useRef, useImperativeHandle } fr

import { useEventCallback, useId } from '@react-devui/hooks';
import { CloseOutlined, LoadingOutlined } from '@react-devui/icons';
import { findNested, getClassName, getOriginalSize, getVerticalSidePosition } from '@react-devui/utils';
import { findNested, getClassName, getVerticalSidePosition } from '@react-devui/utils';

import { useGeneralContext, useDValue } from '../../hooks';
import { cloneHTMLElement, registerComponentMate, TTANSITION_DURING_POPUP, WINDOW_SPACE } from '../../utils';
Expand Down Expand Up @@ -277,7 +277,7 @@ function Cascader<V extends DId, T extends DCascaderItem<V>>(
const [transformOrigin, setTransformOrigin] = useState<string>();
const updatePosition = useEventCallback(() => {
if (visible && boxRef.current && popupRef.current) {
const { height } = getOriginalSize(popupRef.current);
const height = popupRef.current.offsetHeight;
const maxWidth = window.innerWidth - WINDOW_SPACE * 2;
const width = Math.min(popupRef.current.scrollWidth, maxWidth);
const { top, left, transformOrigin } = getVerticalSidePosition(
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, { useImperativeHandle, useRef, useState } from 'react';
import ReactDOM from 'react-dom';

import { useEventCallback, useId, useRefExtra } from '@react-devui/hooks';
import { getClassName, getOriginalSize, getVerticalSidePosition, scrollToView } from '@react-devui/utils';
import { getClassName, getVerticalSidePosition, scrollToView } from '@react-devui/utils';

import { useMaxIndex, useDValue } from '../../hooks';
import { registerComponentMate, TTANSITION_DURING_POPUP, WINDOW_SPACE } from '../../utils';
Expand Down Expand Up @@ -181,7 +181,7 @@ function Dropdown<ID extends DId, T extends DDropdownItem<ID>>(
const [arrowPosition, setArrowPosition] = useState<React.CSSProperties>();
const updatePosition = useEventCallback(() => {
if (visible && childRef.current && dropdownRef.current) {
const { width, height } = getOriginalSize(dropdownRef.current);
const [width, height] = [dropdownRef.current.offsetWidth, dropdownRef.current.offsetHeight];
const { top, left, transformOrigin, arrowPosition } = getVerticalSidePosition(
childRef.current,
{ width, height },
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/dropdown/Sub.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ReactDOM from 'react-dom';

import { useEventCallback, useRefExtra } from '@react-devui/hooks';
import { RightOutlined } from '@react-devui/icons';
import { checkNodeExist, getClassName, getHorizontalSidePosition, getOriginalSize } from '@react-devui/utils';
import { checkNodeExist, getClassName, getHorizontalSidePosition } from '@react-devui/utils';

import { TTANSITION_DURING_POPUP, WINDOW_SPACE } from '../../utils';
import { DPopup } from '../_popup';
Expand Down Expand Up @@ -58,7 +58,7 @@ function Sub(props: DSubProps, ref: React.ForwardedRef<() => void>): JSX.Element
const [transformOrigin, setTransformOrigin] = useState<string>();
const updatePosition = useEventCallback(() => {
if (isVisible && ulRef.current && liRef.current) {
const { width, height } = getOriginalSize(ulRef.current);
const [width, height] = [ulRef.current.offsetWidth, ulRef.current.offsetHeight];
const { top, left, transformOrigin } = getHorizontalSidePosition(
liRef.current,
{ width, height },
Expand Down
9 changes: 4 additions & 5 deletions packages/ui/src/components/menu/Sub.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, { useState, useRef, useImperativeHandle, useEffect } from 'react';
import ReactDOM from 'react-dom';

import { useEventCallback, useRefExtra } from '@react-devui/hooks';
import { checkNodeExist, getClassName, getHorizontalSidePosition, getOriginalSize, getVerticalSidePosition } from '@react-devui/utils';
import { checkNodeExist, getClassName, getHorizontalSidePosition, getVerticalSidePosition } from '@react-devui/utils';

import { useMaxIndex } from '../../hooks';
import { TTANSITION_DURING_BASE, TTANSITION_DURING_POPUP, WINDOW_SPACE } from '../../utils';
Expand Down Expand Up @@ -98,12 +98,11 @@ function Sub(props: DSubProps, ref: React.ForwardedRef<() => void>): JSX.Element
const [transformOrigin, setTransformOrigin] = useState<string>();
const updatePosition = useEventCallback(() => {
if (isVisible && ulRef.current && liRef.current) {
const size = getOriginalSize(ulRef.current);
const height = size.height;
const height = ulRef.current.offsetHeight;

let width = size.width;
let width = ulRef.current.offsetWidth;
if (inHorizontalNav) {
width = liRef.current.getBoundingClientRect().width - 32;
width = liRef.current.offsetWidth - 32;
}

const { top, left, transformOrigin } = inHorizontalNav
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ export const DModal: {
if (isUndefined(ROOT_DATA.clickEvent) || performance.now() - ROOT_DATA.clickEvent.time > 100) {
dataRef.current.transformOrigin = undefined;
} else if (modalContentRef.current) {
const left = `${(window.innerWidth - modalContentRef.current.clientWidth) / 2}px`;
const top = dTop === 'center' ? `${(window.innerHeight - modalContentRef.current.clientHeight) / 2}px` : topStyle;
const left = `${(window.innerWidth - modalContentRef.current.offsetWidth) / 2}px`;
const top = dTop === 'center' ? `${(window.innerHeight - modalContentRef.current.offsetHeight) / 2}px` : topStyle;
dataRef.current.transformOrigin = `calc(${ROOT_DATA.clickEvent.e.clientX}px - ${left}) calc(${ROOT_DATA.clickEvent.e.clientY}px - ${top})`;
}
}}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/notification/Notification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function DNotification(props: DNotificationProps & { dVisible: boolean })

case 'leave':
if (panelRef.current) {
const { height } = panelRef.current.getBoundingClientRect();
const height = panelRef.current.offsetHeight;
transitionStyle = { height, overflow: 'hidden' };
}
break;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/progress/Progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export function DProgress(props: DProgressProps): JSX.Element | null {
if (progressRef.current) {
const el = progressRef.current.querySelector(`[data-progress-svg="${uniqueId}"]`);
if (el) {
setLineWidth(el.getBoundingClientRect().width);
setLineWidth(el.clientWidth);
}
}
});
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/src/components/select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React, { useState, useCallback, useMemo, useRef, useImperativeHandle } fr

import { useEventCallback, useId } from '@react-devui/hooks';
import { CloseOutlined, LoadingOutlined, PlusOutlined } from '@react-devui/icons';
import { findNested, getClassName, getOriginalSize, getVerticalSidePosition } from '@react-devui/utils';
import { findNested, getClassName, getVerticalSidePosition } from '@react-devui/utils';

import { useGeneralContext, useDValue } from '../../hooks';
import { cloneHTMLElement, registerComponentMate, TTANSITION_DURING_POPUP, WINDOW_SPACE } from '../../utils';
Expand Down Expand Up @@ -304,8 +304,8 @@ function Select<V extends DId, T extends DSelectItem<V>>(
const [transformOrigin, setTransformOrigin] = useState<string>();
const updatePosition = useEventCallback(() => {
if (visible && boxRef.current && popupRef.current) {
const width = Math.min(boxRef.current.getBoundingClientRect().width, window.innerWidth - WINDOW_SPACE * 2);
const { height } = getOriginalSize(popupRef.current);
const width = Math.min(boxRef.current.offsetWidth, window.innerWidth - WINDOW_SPACE * 2);
const height = popupRef.current.offsetHeight;
const { top, left, transformOrigin } = getVerticalSidePosition(
boxRef.current,
{ width, height },
Expand Down
28 changes: 14 additions & 14 deletions packages/ui/src/components/slides/Slides.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ export function DSlides<ID extends DId, T extends DSlideItem<ID>>(props: DSlides
slideEls.forEach((el) => {
const index = Number((el as HTMLDivElement).dataset['index']);
if (index < activeIndex) {
size += el[dVertical ? 'clientHeight' : 'clientWidth'];
size += el[dVertical ? 'offsetHeight' : 'offsetWidth'];
} else if (index === activeIndex) {
slidesRef.current!.style.height = el.clientHeight + 'px';
slidesRef.current!.style.height = (el as HTMLDivElement).offsetHeight + 'px';
}
});

Expand Down Expand Up @@ -152,38 +152,38 @@ export function DSlides<ID extends DId, T extends DSlideItem<ID>>(props: DSlides
if (distance > 0) {
let size = 0;
for (let index = activeIndex - 1; index >= 0; index--) {
size += els[index][dVertical ? 'clientHeight' : 'clientWidth'];
size += els[index][dVertical ? 'offsetHeight' : 'offsetWidth'];
}
const distanceValue =
Math.abs(distance) > size
? size +
Math.sin(
Math.min((Math.abs(distance) - size) / (els[0][dVertical ? 'clientHeight' : 'clientWidth'] * 3), 1) * (Math.PI / 2)
Math.min((Math.abs(distance) - size) / (els[0][dVertical ? 'offsetHeight' : 'offsetWidth'] * 3), 1) * (Math.PI / 2)
) *
els[0][dVertical ? 'clientHeight' : 'clientWidth']
els[0][dVertical ? 'offsetHeight' : 'offsetWidth']
: distance;
setDragDistance(distanceValue);
setDragOpacity({
index: activeIndex,
value:
activeIndex === 0
? 1
: Math.max(1 - Math.abs(distanceValue) / els[activeIndex - 1][dVertical ? 'clientHeight' : 'clientWidth'], 0),
: Math.max(1 - Math.abs(distanceValue) / els[activeIndex - 1][dVertical ? 'offsetHeight' : 'offsetWidth'], 0),
});
} else {
let size = 0;
for (let index = activeIndex + 1; index < dList.length; index++) {
size += els[index][dVertical ? 'clientHeight' : 'clientWidth'];
size += els[index][dVertical ? 'offsetHeight' : 'offsetWidth'];
}
const distanceValue =
Math.abs(distance) > size
? -(
size +
Math.sin(
Math.min((Math.abs(distance) - size) / (els[dList.length - 1][dVertical ? 'clientHeight' : 'clientWidth'] * 3), 1) *
Math.min((Math.abs(distance) - size) / (els[dList.length - 1][dVertical ? 'offsetHeight' : 'offsetWidth'] * 3), 1) *
(Math.PI / 2)
) *
els[dList.length - 1][dVertical ? 'clientHeight' : 'clientWidth']
els[dList.length - 1][dVertical ? 'offsetHeight' : 'offsetWidth']
)
: distance;
setDragDistance(distanceValue);
Expand All @@ -192,7 +192,7 @@ export function DSlides<ID extends DId, T extends DSlideItem<ID>>(props: DSlides
value:
activeIndex === dList.length - 1
? 1
: Math.min(Math.abs(distanceValue) / els[activeIndex + 1][dVertical ? 'clientHeight' : 'clientWidth'], 1),
: Math.min(Math.abs(distanceValue) / els[activeIndex + 1][dVertical ? 'offsetHeight' : 'offsetWidth'], 1),
});
}
}
Expand All @@ -210,8 +210,8 @@ export function DSlides<ID extends DId, T extends DSlideItem<ID>>(props: DSlides
let newIndex = activeIndex;
let size = 0;
for (let index = activeIndex - 1; index >= 0; index--) {
if (Math.abs(dragDistance) > size + els[index][dVertical ? 'clientHeight' : 'clientWidth'] / 2) {
size += els[index][dVertical ? 'clientHeight' : 'clientWidth'];
if (Math.abs(dragDistance) > size + els[index][dVertical ? 'offsetHeight' : 'offsetWidth'] / 2) {
size += els[index][dVertical ? 'offsetHeight' : 'offsetWidth'];
newIndex = index;
} else {
break;
Expand All @@ -228,8 +228,8 @@ export function DSlides<ID extends DId, T extends DSlideItem<ID>>(props: DSlides
let newIndex = activeIndex;
let size = 0;
for (let index = activeIndex + 1; index < dList.length; index++) {
if (Math.abs(dragDistance) > size + els[index][dVertical ? 'clientHeight' : 'clientWidth'] / 2) {
size += els[index][dVertical ? 'clientHeight' : 'clientWidth'];
if (Math.abs(dragDistance) > size + els[index][dVertical ? 'offsetHeight' : 'offsetWidth'] / 2) {
size += els[index][dVertical ? 'offsetHeight' : 'offsetWidth'];
newIndex = index;
} else {
break;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/spinner/Spinner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function DSpinner(props: DSpinnerProps): JSX.Element | null {
dDuring={TTANSITION_DURING_BASE}
onEnter={() => {
if (!dAlone && spinnerRef.current && containerRef.current) {
containerRef.current.style.height = `${spinnerRef.current.clientHeight}px`;
containerRef.current.style.height = `${spinnerRef.current.offsetHeight}px`;
}
}}
dDestroyWhenLeaved
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/toast/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function DToast(props: DToastProps & { dVisible: boolean }): JSX.Element

case 'leave':
if (panelRef.current) {
const { height } = panelRef.current.getBoundingClientRect();
const height = panelRef.current.offsetHeight;
transitionStyle = { height, overflow: 'hidden' };
}
break;
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/src/components/tree-select/TreeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import React, { useCallback, useState, useMemo, useRef, useImperativeHandle } fr

import { useEventCallback, useId } from '@react-devui/hooks';
import { CloseOutlined, LoadingOutlined } from '@react-devui/icons';
import { findNested, getClassName, getOriginalSize, getVerticalSidePosition } from '@react-devui/utils';
import { findNested, getClassName, getVerticalSidePosition } from '@react-devui/utils';

import { useGeneralContext, useDValue } from '../../hooks';
import { cloneHTMLElement, registerComponentMate, TTANSITION_DURING_POPUP, WINDOW_SPACE } from '../../utils';
Expand Down Expand Up @@ -306,8 +306,8 @@ function TreeSelect<V extends DId, T extends DTreeItem<V>>(
const [transformOrigin, setTransformOrigin] = useState<string>();
const updatePosition = useEventCallback(() => {
if (visible && boxRef.current && popupRef.current) {
const boxWidth = boxRef.current.getBoundingClientRect().width;
const { height } = getOriginalSize(popupRef.current);
const boxWidth = boxRef.current.offsetWidth;
const height = popupRef.current.offsetHeight;
const maxWidth = window.innerWidth - WINDOW_SPACE * 2;
const width = Math.min(Math.max(popupRef.current.scrollWidth, boxWidth), maxWidth);
const { top, left, transformOrigin } = getVerticalSidePosition(
Expand Down
21 changes: 0 additions & 21 deletions packages/utils/src/getOriginalSize.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export { copy } from './copy';
export { findNested } from './findNested';
export { getClassName } from './getClassName';
export { getOffsetToRoot } from './getOffsetToRoot';
export { getOriginalSize } from './getOriginalSize';
export { getUID } from './getUID';
export { isSimpleArrayEqual } from './isSimpleArrayEqual';
export { saveFile } from './saveFile';
Expand Down
Loading

0 comments on commit eec6be0

Please sign in to comment.