放大镜效果图
放大镜代码 (响应式)
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>
);
}