放大镜效果图
![放大镜](https://i-blog.csdnimg.cn/blog_migrate/bbd2c6fb3096e0efe56450ab4f6259e9.png)
放大镜代码 (响应式)
import React, { useEffect, useState, useMemo } from "react";
function fetMainParams (clientWidth = 500) {
const PARAMS = {
scale: 2,
width: clientWidth,
height: clientWidth + 100,
}
const mouseRadiusW = PARAMS.width / PARAMS.scale / 2;
const mouseRadiusH = PARAMS.height / PARAMS.scale / 2;
const ClassObj = {
imgContainer: {
width: `${PARAMS.width}px`,
height: `${PARAMS.height}px`,
border: "1px solid #ccc",
cursor: "move",
position: "relative"
},
maskBlock: {
position: "absolute",
top: "0",
left: "0",
width: "100%",
height: "100%",
zIndex: 100
},
mouseBlock: {
position: "absolute",
top: "0",
left: "0",
width: `${mouseRadiusW * 2}px`,
height: `${mouseRadiusH * 2}px`,
background: "rgba(0,0,0,0.1)",
zIndex: 99
},
magnifierContainer: {
position: "absolute",
left: `${PARAMS.width}px`,
top: "0",
width: `${PARAMS.width}px`,
height: `${PARAMS.height}px`,
border: "1px solid #ccc",
overflow: "hidden",
zIndex: 98
},
imgStyle: {
width: `${PARAMS.width}px`,
height: `${PARAMS.height}px`,
position: "absolute",
top: 0,
left: 0,
transform: `scale(${PARAMS.scale})`,
transformOrigin: "top left"
}
};
return { PARAMS, mouseRadiusW, mouseRadiusH, ClassObj }
}
export default (props) => {
const [imgUrl, setImgUrl] = useState('');
const [{ PARAMS, mouseRadiusW, mouseRadiusH, ClassObj }, setMainParams] = useState(({ PARAMS: {}, mouseRadiusW: 0, mouseRadiusH: 0, ClassObj: {} }));
const [magnifierOff, setMagnifierOff] = useState(false);
const [{ mouseBlock, imgStyle }, setMouseImg] = useState({ mouseBlock: {}, imgStyle: {} });
const calculationBlock = (offsetX, offsetY) => {
const cssStyle = { mouseBlock: { ...mouseBlock }, imgStyle: { ...imgStyle } }
let offsetW = offsetX;
let offsetH = offsetY;
if (offsetX < mouseRadiusW) {
offsetW = mouseRadiusW;
}
else if (offsetX > (PARAMS.width - mouseRadiusW)) {
offsetW = (PARAMS.width - mouseRadiusW);
}
if (offsetY < mouseRadiusH) {
offsetH = mouseRadiusH;
}
else if (offsetY > (PARAMS.height - mouseRadiusH)) {
offsetH = (PARAMS.height - mouseRadiusH);
}
const left = offsetW - mouseRadiusW;
const top = offsetH - mouseRadiusH;
cssStyle.mouseBlock.left = left;
cssStyle.mouseBlock.top = top;
cssStyle.imgStyle.left = -left * PARAMS.scale;
cssStyle.imgStyle.top = -top * PARAMS.scale;
setMouseImg(cssStyle)
};
const mouseEnter = () => {
setMagnifierOff(true)
};
const mouseLeave = () => {
setMagnifierOff(false)
};
const mouseMove = event => {
const e = event.nativeEvent;
calculationBlock(e.offsetX, e.offsetY);
};
const magnifierMemo = useMemo(() => {
if (props.position === 'left') {
return {
...ClassObj.magnifierContainer,
left: `-${PARAMS.width}px`,
}
}
return ClassObj.magnifierContainer;
}, [props.position, ClassObj]);
useEffect(() => {
const clientWidth = document.getElementById('mydiv').clientWidth || 500
const results = fetMainParams(clientWidth)
setMainParams(results)
setMouseImg({ mouseBlock: results.ClassObj.mouseBlock, imgStyle: results.ClassObj.imgStyle })
}, []);
useEffect(() => {
setImgUrl(props.imgUrl)
}, [props.imgUrl]);
return (
<div id="mydiv" style={{ position: 'relative' }}>
<div style={ClassObj.imgContainer}>
<img src={imgUrl} width="100%" height="100%" alt="图片加载失败"/>
<div
style={ClassObj.maskBlock}
onMouseEnter={mouseEnter}
onMouseLeave={mouseLeave}
onMouseMove={mouseMove}
/>
{magnifierOff && <div style={mouseBlock} />}
</div>
{magnifierOff && (
<div style={magnifierMemo}>
<img
style={imgStyle}
src={imgUrl}
alt="图片加载失败"
/>
</div>
)}
</div>
);
}