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

fix: 修复scrollIntoView的参数behavior设置为smooth时引导面板定位异常的问题 #50509 #66

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
4 changes: 2 additions & 2 deletions docs/examples/scrollIntoView.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, useState } from 'react';
import React, {useRef, useState} from 'react';
import Tour from '../../src/index';
import './basic.less';

Expand Down Expand Up @@ -65,7 +65,7 @@ const App = () => {
),
target: () => updateBtnRef.current,
scrollIntoViewOptions: {
block: 'start'
block: 'start', behavior:'smooth'
}
},
{
Expand Down
9 changes: 7 additions & 2 deletions src/hooks/useTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import useEvent from 'rc-util/lib/hooks/useEvent';
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import { useMemo, useState } from 'react';
import type { TourStepInfo } from '..';
import { isInViewPort } from '../util';
import { isInViewPort,debounce } from '../util';

export interface Gap {
offset?: number | [number, number];
Expand Down Expand Up @@ -44,8 +44,8 @@ export default function useTarget(
// Exist target element. We should scroll and get target position
if (!isInViewPort(targetElement) && open) {
targetElement.scrollIntoView(scrollIntoViewOptions);
return;
}

const { left, top, width, height } =
targetElement.getBoundingClientRect();
const nextPosInfo: PosInfo = { left, top, width, height, radius: 0 };
Expand All @@ -62,15 +62,20 @@ export default function useTarget(
}
});

const debounceUpdatePos = debounce(updatePos, 16)

const getGapOffset = (index: number) =>
(Array.isArray(gap?.offset) ? gap?.offset[index] : gap?.offset) ?? 6;

useLayoutEffect(() => {
updatePos();
// update when window resize
window.addEventListener('resize', updatePos);
// update when window scroll stop
window.addEventListener('scroll',debounceUpdatePos)
return () => {
window.removeEventListener('resize', updatePos);
window.removeEventListener('scroll', debounceUpdatePos);
};
}, [targetElement, open, updatePos]);

Expand Down
13 changes: 13 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,16 @@ export function getPlacement(
stepPlacement ?? placement ?? (targetElement === null ? 'center' : 'bottom')
);
}

export function debounce<T extends (...args: any[]) => any>(func: T, wait: number): T {
let timeoutId: ReturnType<typeof setTimeout>;

const debouncedFunc = (...args: Parameters<T>): void => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func(...args);
}, wait);
};

return debouncedFunc as T;
}