Я работаю над этой подсказкой, где, если вы наведете на нее курсор мыши, она покажет подсказку:
![](https://mpen.xyz/share/2020/03/Code_2020-03-15_15-36-19.png)
Но если вы нажмете на нее (пальцем), то она покажу полный экран (для мобильной поддержки):
![](https://mpen.xyz/share/2020/03/Code_2020-03-15_15-37-04.png)
Код выглядит следующим образом:
export default function Tooltip({ message, children }: Props) {
const [showSmallTip, setShowSmallTip] = useState(false);
const [showBigTap, setShowBigTip] = useState(false);
const ref = useRef(null);
const pos = useBoundingBox(ref);
const handleMouseEnter = useCallback(() => {
setShowSmallTip(true);
}, [setShowSmallTip]);
const handleMouseLeave = useCallback(() => {
setShowSmallTip(false);
}, [setShowSmallTip]);
const handleTap = useCallback(() => {
console.log("TAP!")
setShowBigTip(true);
setShowSmallTip(false);
}, [setShowBigTip]);
const closeFullscreen = useCallback((ev:MouseEvent<HTMLElement>) => {
console.log('CLOSE!!!')
ev.stopPropagation();
setShowBigTip(false);
setShowSmallTip(false);
}, [setShowBigTip]);
const onTap = useTap(handleTap);
return <>
<Wrapper ref={ref} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} {...onTap}>
{children}
</Wrapper>
{showSmallTip ? <End container={SCROLL_ROOT}><StyledTooltip style={{ top: pos.bottom, left: (pos.left + pos.right) / 2 }}>{message}</StyledTooltip></End> : null}
{showBigTap ? <End><FullscreenTip onClick={closeFullscreen}><FullscreenText>{message}</FullscreenText></FullscreenTip></End>:null}
</>
}
Где useTap
:
export default function useTap<T = Element>(callback: VoidCallback, options?: Options): TouchEvents<T> {
const data = useRef<TouchData>(Object.create(null));
return useMemo<TouchEvents<T>>(() => {
const opt = { ...DEFAULT_OPTIONS, ...options } as Required<Options>;
return {
onTouchStart(ev) {
data.current = {
time: ev.timeStamp,
x: ev.changedTouches[0].screenX,
y: ev.changedTouches[0].screenY,
}
},
onTouchEnd(ev) {
const mx = ev.changedTouches[0].screenX - data.current.x;
const my = ev.changedTouches[0].screenY - data.current.y;
const moved = Math.sqrt(mx**2 + my**2);
const elapsed = ev.timeStamp - data.current.time;
if (moved < opt.moveThreshold && elapsed < opt.pressDelay) {
// setTimeout(() => {
callback();
// }, 0);
}
}
}
}, [callback, options])
}
Проблема, с которой я столкнулся, заключается в том, что когда вы нажимаете на значок, он открывается и сразу же закрывает полноэкранную подсказку. то есть он печатает
TAP!
CLOSE!!!
одним нажатием.
Теперь я знаю, touchend
срабатывает до click
, но я не могу понять, почему это даже имеет значение ?? Если вы посмотрите на мое размещение обработчиков {...onTap}
и onClick={closeFullscreen}
, то они братья и сестры. События не должны пузыриться таким образом (ни в собственном DOM, ни в React's VDOM ), и я, конечно, не нажал на <FullscreenTip>
, так как же closeFullscreen
запускается?
<End>
это портал.