react如何实现缩放


这篇文章主要讲解了“react如何实现缩放”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“react如何实现缩放”吧! react实现缩放的方法:1、监听onWheel事件;2、设置事件对象event的属性deltaY,当向上滚动时“deltaY0”;3、修改每次滚动时缩放的比例,同时更改transform样式按比例进行缩放即可。react图片缩放、平移(position、transform实现)很多网页都会给文案附上一些图片补充描述,例如在说到地址时,会在旁边附上一张地图,并且在地图上标注该地址。如果附上的图片很小,很难看清楚地址的具体信息,有些产品经理会给图片设计一个可以平移、放大缩小的功能。本文将一一实现上述功能。废话不多说,先给上效果图:主要三个功能点:图片平移图片缩放车站标注图片平移可以监听这三个事件实现:onMouseDown、onMouseMove、onMouseUp
onMouseDown事件记录每次鼠标按下的坐标位置;
onMouseMove事件计算出每次平移的距离,该距离加上拖动前图片距离父元素的距离就等于拖动后图片相对于父元素的距离;
onMouseUp事件触发时,注销或者不让执行onMouseDown、onMouseMove事件,防止只要鼠标移入图片就会平移。这三个事件需要阻止浏览器的默认行为,不然在移动时会自动打开图片。

constWIDTH=1200;constHEIGHT=900;constDynamicStyle=()=>{
constimgRef=React.createRef();
/**图片样式*/const[imgStyle,setImgStyle]=useState({});/**记录鼠标是否按下*/const[mouseDowmFlag,setMouseDowmFlag]=useState(false);/**记录鼠标按下的坐标*/const[mouseDowmPos,setMouseDowmPos]=useState({x:0,y:0})/**鼠标可视区域时,重置鼠标按下的布尔值为false*/useEffect(()=>{document.onmouseover=()=>{if(mouseDowmFlag){setMouseDowmFlag(false);
}
};return()=>{document.onmouseover=null;
};
},[mouseDowmFlag])/**平移*/consthandleMouseDown=(event:React.MouseEvent)=>{const{clientX,clientY}=event;
event.stopPropagation();
event.preventDefault();//阻止浏览器默认行为,拖动会打开图片setMouseDowmFlag(true);//控制只有在鼠标按下后才会执行mousemovesetMouseDowmPos({x:clientX,y:clientY,
});
};consthandleMouseMove=(event:React.MouseEvent)=>{
event.stopPropagation();
event.preventDefault();const{clientX,clientY}=event;constdiffX=clientX-mouseDowmPos.x;constdiffY=clientY-mouseDowmPos.y;if(!mouseDowmFlag||(diffX===0&&diffY===0))return;const{offsetLeft,offsetTop}=imgRef.currentasHTMLImageElement;constoffsetX=parseInt(`${diffX+offsetLeft}`,10);constoffsetY=parseInt(`${diffY+offsetTop}`,10);setMouseDowmPos({x:clientX,y:clientY,
});setImgStyle({
...imgStyle,left:offsetX,top:offsetY,
});
};consthandleMouseUp=(event:React.MouseEvent)=>{
event.stopPropagation();
event.preventDefault();setMouseDowmFlag(false);
};return(
) }

图片缩放可以监听onWheel事件,事件对象event有一个记录滚轮滚动的属性deltaY,当向上滚动时deltaY,向下滚动时deltaY>0。每次滚动修改其缩放的比例,同时更改transform样式按比例进行缩放。

constWIDTH=1200;constHEIGHT=900;constSCALE=0.2;constDynamicStyle=()=>{constimgRef=React.createRef();/**初始化缩放比例,默认为1*/const[rate,setRate]=useState(1);/**图片样式*/const[imgStyle,setImgStyle]=useState({});/**记录鼠标是否按下*/const[mouseDowmFlag,setMouseDowmFlag]=useState(false);/**记录鼠标按下的坐标*/const[mouseDowmPos,setMouseDowmPos]=useState({x:0,y:0})/**图片现在大小*/const[initial,setInitial]=useState({width:WIDTH,height:HEIGHT});useEffect(()=>{const{naturalWidth,naturalHeight,width,height}=imgRef.currentasHTMLImageElement;setInitial({width,height});//eslint-disable-next-linereact-hooks/exhaustive-deps
},[])//console.log(natural,initial)useEffect(()=>{document.onmouseover=()=>{if(mouseDowmFlag){setMouseDowmFlag(false);
}
};return()=>{document.onmouseover=null;
};
},[mouseDowmFlag])/**缩放*/consthandleWheelImage=(event:React.WheelEvent)=>{//向上为负,向下为正constbigger=event.deltaY>0?-1:1;//transform偏移量consttransformX=-initial.width/2;consttransformY=-initial.height/2;if(bigger>0&&rate1){constshrinkRate=rate-SCALE;setImgStyle({
...imgStyle,transform:`matrix(${shrinkRate},0,0,${shrinkRate},${transformX},${transformY})`,
});setRate(shrinkRate);
}
}/**平移*/consthandleMouseDown=(event:React.MouseEvent)=>{const{clientX,clientY}=event;
event.stopPropagation();
event.preventDefault();//阻止浏览器默认行为,拖动会打开图片setMouseDowmFlag(true);//控制只有在鼠标按下后才会执行mousemovesetMouseDowmPos({x:clientX,y:clientY,
});
};consthandleMouseMove=(event:React.MouseEvent)=>{
event.stopPropagation();
event.preventDefault();const{clientX,clientY}=event;constdiffX=clientX-mouseDowmPos.x;constdiffY=clientY-mouseDowmPos.y;if(!mouseDowmFlag||(diffX===0&&diffY===0))return;const{offsetLeft,offsetTop}=imgRef.currentasHTMLImageElement;constoffsetX=parseInt(`${diffX+offsetLeft}`,10);constoffsetY=parseInt(`${diffY+offsetTop}`,10);setMouseDowmPos({x:clientX,y:clientY,
});setImgStyle({
...imgStyle,left:offsetX,top:offsetY,
});
};consthandleMouseUp=(event:React.MouseEvent)=>{
event.stopPropagation();
event.preventDefault();setMouseDowmFlag(false);
};return(
) }

.imgArea{position:relative;width:1200px;height:900px;margin:auto;border:1pxsolid#da2727;overflow:hidden;
&>img{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);cursor:move;
}
}

如果没有设置transformOrigin,默认是相对于图片中心进行缩放,但是在初始为了让图片在可视区域内水平垂直居中,使用了transform: translate(-50%, -50%);,因此为了缩放时相对于图片中心点,需要设置matrix的第5、6个参数矫正transformOrigintransform: matrix(${shrinkRate}, 0, 0, ${shrinkRate}, ${transformX}, ${transformY})首先,定义一个常量表示图标的坐标,这个坐标是相对于原始图片左上角的定位。

constimgInfo={lableLeft:"1900",lableTop:"2000",}

这里,解释一下原始图的概念:
随便在网上查看一个图片元素,比如上面。1200 x 900是页面定的图片大小,但图片还有一个真实大小4535 x 3402。要计算图标在没有平移缩放时的初始坐标之前,需要算出图片的缩放比例(不是上面的rate):

/**图片原始大小,默认设置为1是防止计算图片原始大小与初始大小比例出现无穷大*/const[natural,setNatural]=useState({width:1,height:1});/**图片现在大小*/const[initial,setInitial]=useState({width:WIDTH,height:HEIGHT});useEffect(()=>{const{naturalWidth,naturalHeight,width,height}=imgRef.currentasHTMLImageElement;setNatural({width:naturalWidth,height:naturalHeight});setInitial({width,height});//eslint-disable-next-linereact-hooks/exhaustive-deps},[])
//初始图片缩放比例(图片有原始的图片大小)constimgScaleRateX=initial.width/natural.width;constimgScaleRateY=initial.height/natural.height;

图标初始的坐标就可以计算出:

constlabelLeft=parseInt(`${imgInfo.lableLeft}`,10)*imgScaleRateX;constlabelTop=parseInt(`${imgInfo.lableTop}`,10)*imgScaleRateY;

当图片平移时,图标也需要跟着平移,这是的坐标计算:

//图标相对父元素坐标=图标位置坐标+图片坐标constlabelLeft=parseInt(`${imgInfo.lableLeft}`,10)*imgScaleRateX+Number(imgStyle.left||WIDTH/2);
constlabelTop=parseInt(`${imgInfo.lableTop}`,10)*imgScaleRateY+Number(imgStyle.top||HEIGHT/2);

当图片缩放时,图标需要随着图片一起缩放。如果没有对图标设置transformOrigin,默认时相对图标的中心缩放的。为了保证图标随着图片一起缩放,那就必须使得图片和图标的缩放参照原点相同,图标的transformOrigin应该设置为相对于图片原点的距离。

constlabelTransformOrigin=()=>{return`${initial.width/2-Number(imgInfo.lableLeft)*imgScaleRateX}px${
initial.height/2-Number(imgInfo.lableTop)*imgScaleRateY
}px`;
}

整体代码示例:

constimgInfo={
lableLeft:"1900",
lableTop:"2000",
}

constWIDTH=1200;
constHEIGHT=900;
constSCALE=0.2;

constDynamicStyle=()=>{

constimgRef=React.createRef();
/**初始化缩放比例,默认为1*/
const[rate,setRate]=useState(1);
/**图片样式*/
const[imgStyle,setImgStyle]=useState({});
/**记录鼠标是否按下*/
const[mouseDowmFlag,setMouseDowmFlag]=useState(false);
/**记录鼠标按下的坐标*/
const[mouseDowmPos,setMouseDowmPos]=useState({x:0,y:0})
/**图片原始大小,默认设置为1是防止计算图片原始大小与初始大小比例出现无穷大*/
const[natural,setNatural]=useState({width:1,height:1});
/**图片现在大小*/
const[initial,setInitial]=useState({width:WIDTH,height:HEIGHT});

useEffect(()=>{
const{naturalWidth,naturalHeight,width,height}=imgRef.currentasHTMLImageElement;
setNatural({width:naturalWidth,height:naturalHeight});
setInitial({width,height});
//eslint-disable-next-linereact-hooks/exhaustive-deps
},[])

useEffect(()=>{
document.onmouseover=()=>{
if(mouseDowmFlag){
setMouseDowmFlag(false);
}
};
return()=>{
document.onmouseover=null;
};
},[mouseDowmFlag])

/**缩放*/
consthandleWheelImage=(event:React.WheelEvent)=>{
//向上为负,向下为正
constbigger=event.deltaY>0?-1:1;
//transform偏移量
consttransformX=-initial.width/2;
consttransformY=-initial.height/2;
if(bigger>0&&rate1){
constshrinkRate=rate-SCALE;
setImgStyle({
...imgStyle,
transform:`matrix(${shrinkRate},0,0,${shrinkRate},${transformX},${transformY})`,
});
setRate(sh免费云主机域名rinkRate);
}
}

/**平移*/
consthandleMouseDown=(event:React.MouseEvent)=>{
const{clientX,clientY}=event;
event.stopPropagation();
event.preventDefault();//阻止浏览器默认行为,拖动会打开图片
setMouseDowmFlag(true);//控制只有在鼠标按下后才会执行mousemove
setMouseDowmPos({
x:clientX,
y:clientY,
});
};

consthandleMouseMove=(event:React.MouseEvent)=>{
event.stopPropagation();
event.preventDefault();
const{clientX,clientY}=event;
constdiffX=clientX-mouseDowmPos.x;
constdiffY=clientY-mouseDowmPos.y;
if(!mouseDowmFlag||(diffX===0&&diffY===0))return;
const{offsetLeft,offsetTop}=imgRef.currentasHTMLImageElement;
constoffsetX=parseInt(`${diffX+offsetLeft}`,10);
constoffsetY=parseInt(`${diffY+offsetTop}`,10);

setMouseDowmPos({
x:clientX,
y:clientY,
});
setImgStyle({
...imgStyle,
left:offsetX,
top:offsetY,
});
};

consthandleMouseUp=(event:React.MouseEvent)=>{
event.stopPropagation();
event.preventDefault();
setMouseDowmFlag(false);
};

//初始图片缩放比例(图片有原始的图片大小)
constimgScaleRateX=initial.width/natural.width;
constimgScaleRateY=initial.height/natural.height;

constlabelTransformOrigin=()=>{
return`${initial.width/2-Number(imgInfo.lableLeft)*imgScaleRateX}px${
initial.height/2-Number(imgInfo.lableTop)*imgScaleRateY
}px`;
}

/**图标位置计算*/
constlabelStyle=():React.CSSProperties=>{
consttransformX=-initial.width/2;
consttransformY=-initial.height/2;
//图标相对父元素坐标=图标初始位置坐标+平移量
constlabelLeft=parseInt(`${imgInfo.lableLeft}`,10)*imgScaleRateX+Number(imgStyle.left||WIDTH/2);
constlabelTop=parseInt(`${imgInfo.lableTop}`,10)*imgScaleRateY+Number(imgStyle.top||HEIGHT/2);
return{
left:labelLeft,
top:labelTop,
transformOrigin:labelTransformOrigin(),
transform:`matrix(${rate},0,0,${rate},${transformX},${transformY})`,
}
}


return(
) }

感谢各位的阅读,以上就是“react如何实现缩放”的内容了,经过本文的学习后,相信大家对react如何实现缩放这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是百云主机,小编将为大家推送更多相关知识点的文章,欢迎关注!

相关推荐: SpringBoot配置如何绑定

这篇文章主要介绍“SpringBoot配置如何绑定”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringBoot配置如何绑定”文章能帮助大家解决问题。所谓“配置绑定”就是把配置文件中的值与 JavaBean 中对应…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 03/02 17:48
下一篇 03/02 17:48

相关推荐