持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
早上打开掘金刷文章的时候,看到了这个
心里想着,那我试一下吧。不用,对于移动端的部分,这边我也没有进行尝试。防抖的部分,大家可以自己实现一个函数,也可以使用现成的 loadsh 进行包装。
原理原文作者已经讲得很明白了。
主要讲一下React 和 jq 一些不同的地方
- HTML 结构中的 class 需要换成 className。
- 获取元素,在 React Hooks 中使用 useRef + ref 来实现。
- 绑定鼠标事件,直接在元素上,使用 onMouseEnter,onMouseLeave,onMouseMove。
<>
<div className="container">
<div className="place"></div>
<div className="inner">
<img
width={200}
height={200}
ref={originImg}
src="https://cdn.pixabay.com/photo/2022/02/23/14/50/houses-7030773__340.jpg"
onMouseEnter={onMouseEnter}
/>
</div>
</div>
<div
className="zoom-holder"
style={{
left: newData.left,
top: newData.top,
display: showPalce ? 'block' : 'none'
}
}>
<div className="img_wrapper">
<img
ref={newinImg}
style={{
left: newImgData.left,
top: newImgData.top
}}
src="https://cdn.pixabay.com/photo/2022/02/23/14/50/houses-7030773__340.jpg"
/>
</div>
</div>
<div
ref={zoomOverlay}
onMouseLeave={onMouseLeave}
onMouseMove={onMouseMove}
className="zoom-img-overlay"
style={{
left: orgImg.left,
top: orgImg.top,
width: orgImg.width,
height: orgImg.height
}}
></div>
</>
- 使用 useState 来存储数据
const zoomOverlay = useRef<HTMLDivElement>(null);
const originImg = useRef<HTMLImageElement>(null);
const newinImg = useRef<HTMLImageElement>(null);
const [orgImg, setOrgImg] = useState<Obj>({
left: 0,
top: 0,
width: 0,
height: 0
});
const [newImg, setNewImg] = useState<Obj2>({
width: 0,
height: 0
});
const [newData, setNewData] = useState<Obj1>({
left: 0,
top: 0
});
const [newImgData, setNewImgData] = useState<Obj1>({
left: 0,
top: 0
})
const [showPalce, setShowPalce] = useState<boolean>(false);
当触发事件的时候,改变位置
原来的文章中使用 zoomOverlay.css('left') ,这里我们使用 zoomOverlay?.current?.offsetLeft!。
对于 top , width,height ,我们也是进行同样的操作。
const onMouseLeave = () => {
setShowPalce(false);
}
const onMouseMove = (e: any) => {
const moveX = e.pageX - zoomOverlay?.current?.offsetLeft!;
const moveY = e.pageY - zoomOverlay?.current?.offsetTop!;
const lastX = moveX / (orgImg?.width! / newImg?.width!);
const lastY = moveY / (orgImg?.height! / newImg?.height!);
setNewData({
left: e.pageX - 150,
top: e.pageY - 150
})
setNewImgData({
left: -(lastX - 150),
top: -(lastY - 150)
})
setShowPalce(true);
}
const onMouseEnter = () => {
setOrgImg({
left: originImg?.current?.offsetLeft!,
top: originImg?.current?.offsetTop!,
width: originImg?.current?.offsetWidth!,
height: originImg?.current?.offsetHeight!
});
setNewImg({
width: newinImg?.current?.width!,
height: newinImg?.current?.height!
});
}
写到最后,其实发现,代码还是有点冗余的。不过,算是实现了基本的效果吧。