Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
4 changes: 2 additions & 2 deletions docs/examples/scrollIntoView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const App = () => {
>
Create
</button>
<div style={{ height: 1000 }} />
<div style={{ height: 1500 }} />
<button className="ant-target" ref={updateBtnRef}>
Update
</button>
Expand Down Expand Up @@ -65,7 +65,7 @@ const App = () => {
),
target: () => updateBtnRef.current,
scrollIntoViewOptions: {
block: 'start'
block: 'start', behavior:'smooth'
}
},
{
Expand Down
21 changes: 19 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,32 @@ export default function useTarget(
}
});


let ticking = false;
const debounceUpdatePos = debounce(updatePos,1000/60+0.1);
const scrollUpdatePos = window.requestAnimationFrame ? ()=>{
if (!ticking) {
window.requestAnimationFrame(() => {
debounceUpdatePos();
ticking = false;
});
ticking = true;
}
}: debounce(updatePos,1000/60*3)


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',scrollUpdatePos)
return () => {
window.removeEventListener('resize', updatePos);
window.removeEventListener('scroll', scrollUpdatePos);
};
}, [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;
}