首先知道几个页面位置信息的apicss
补充:html
这一版主要是在小图右侧放一个大图,经过大图移动位置以及利用层级关系,显示大图的部分区域,展示放大的效果. 计算公式: 大图的left = -(左侧图片内滑块left / (左侧图片宽度 - 滑块宽度)) * (右侧大图宽度 - 右侧大图展示区域宽度)api
页面结构很简单,总的来讲就是须要两张图片,一张小图片和一张如出一辙的大图片,主要复杂的是js中的计算部分:浏览器
<div id="demo">
<!-- 左边的小图 -->
<div id="small-box">
<div id="mark"></div>
<!-- 放大镜 -->
<div id="float-box"></div>
<img src="small.jpg"/>
</div>
<!-- 显示的大图 -->
<div id="big-box">
<img src="big.jpg"/>
</div>
</div>
复制代码
<style>
* {
margin: 0;
padding: 0
}
#demo {
display: block;
width: 400px;
height: 255px;
margin: 50px;
position: relative;
border: 1px solid #ccc;
}
#small-box {
position: relative;
z-index: 1;
}
#float-box {
display: none;
width: 160px;
height: 120px;
position: absolute;
background: #ffffcc;
border: 1px solid #ccc;
filter: alpha(opacity=50);
opacity: 0.5;
}
#mark {
position: absolute;
display: block;
width: 400px;
height: 255px;
background-color: #fff;
filter: alpha(opacity=0);
opacity: 0;
z-index: 10;
}
#big-box {
display: none;
position: absolute;
top: 0;
left: 460px;
width: 400px;
height: 300px;
overflow: hidden;
border: 1px solid #ccc;
z-index: 1;;
}
#big-box img {
position: absolute;
z-index: 5
}
</style>
复制代码
此时咱们页面上就只有一张小图片markdown
<script>
//页面加载完毕后执行
window.onload = function () {
var objDemo = document.getElementById("demo");
var objSmallBox = document.getElementById("small-box");
var objMark = document.getElementById("mark");
var objFloatBox = document.getElementById("float-box");
var objBigBox = document.getElementById("big-box");
var objBigBoxImage = objBigBox.getElementsByTagName("img")[0];
//鼠标一如事件
objMark.onmouseover = function () {
objFloatBox.style.display = "block"
objBigBox.style.display = "block"
}
//鼠标移出事件
objMark.onmouseout = function () {
objFloatBox.style.display = "none"
objBigBox.style.display = "none"
}
//鼠标移动事件
objMark.onmousemove = function (ev) {
var _event = ev || window.event; //兼容多个浏览器的event参数模式
var left = _event.clientX - objDemo.offsetLeft - objSmallBox.offsetLeft - objFloatBox.offsetWidth / 2;
var top = _event.clientY - objDemo.offsetTop - objSmallBox.offsetTop - objFloatBox.offsetHeight / 2;
if (left < 0) {
left = 0;
} else if (left > (objMark.offsetWidth - objFloatBox.offsetWidth)) {
left = objMark.offsetWidth - objFloatBox.offsetWidth;
}
if (top < 0) {
top = 0;
} else if (top > (objMark.offsetHeight - objFloatBox.offsetHeight)) {
top = objMark.offsetHeight - objFloatBox.offsetHeight;
}
objFloatBox.style.left = left + "px";
objFloatBox.style.top = top + "px";
var percentX = left / (objMark.offsetWidth - objFloatBox.offsetWidth);
var percentY = top / (objMark.offsetHeight - objFloatBox.offsetHeight);
objBigBoxImage.style.left = -percentX * (objBigBoxImage.offsetWidth - objBigBox.offsetWidth) + "px";
objBigBoxImage.style.top = -percentY * (objBigBoxImage.offsetHeight - objBigBox.offsetHeight) + "px";
}
}
</script>
复制代码
所谓优雅版就是把鼠标变成放大镜,这样就会有比较真实的用放大镜看东西的效果函数
大体实现思路以下:url
1)原图部分添加mouseover监听函数,在鼠标移入原图后,获取鼠标距离原图的top和left的位置spa
2)在鼠标放大镜区域,设置区域背景为放大后的图片,设置为backgroundcode
3)反向计算放大后图片应该移动的距离,设置background-positionorm
html部分代码很是简单,就是一个原图背景图,还有就是两个不显示的img元素,这两个不显示的元素,主要是用来获取图片的宽高
<div id="background" className={styles.originImage} style={{backgroundImage: `url(${url})`}}>
<img src={url} />
<img id="bigger" src={url} />
<div id="manifier" className={styles.biggerImage} style={{backgroundImage: `url(${url})`}} />
</div>
复制代码
js代码主要分为两部分
1)监听鼠标在原图上的移动
const listenBackMousemove = (e: globalThis.MouseEvent) => {
if (!manifier || !background) return
let left = e.offsetX - manifier.offsetWidth / 2,
top = e.offsetY - manifier.offsetHeight / 2
if (left < 0) left = 0
else if (left > background.offsetWidth - manifier.offsetWidth)
left = background.offsetWidth - manifier.offsetWidth
if (top < 0) top = 0
else if (top > background.offsetHeight - manifier.offsetHeight)
top = background.offsetHeight - manifier.offsetHeight
manifier.style.visibility = 'visible'
manifier.style.left = left + 'px'
manifier.style.top = top + 'px'
imgMove(left, top)
}
复制代码
2)根据鼠标在原图上移动的距离,反向计算放大后的图片应该移动的距离
const imgMove = (left: number, top: number) => {
if (!bigger || !background || !manifier) return
const imgWidth = bigger.offsetWidth
const imgHeight = bigger.offsetHeight
const backHeight = background.offsetHeight
const backWidth = background.offsetWidth
const manHeight = manifier.offsetHeight
const manWidth = manifier.offsetWidth
const rateX = left / (backWidth - manWidth)
const rateY = top / (backHeight - manHeight)
let imgLeft = -(rateX * (imgWidth - manWidth)),
imgTop = -(rateY * (imgHeight - manHeight))
if (imgLeft > 0) imgLeft = 0
else if (imgLeft < -(imgWidth - manWidth)) imgLeft = -(imgWidth - manWidth)
if (imgTop > 0) imgTop = 0
else if (imgTop < -(imgHeight - manHeight)) imgTop = -(imgHeight - manHeight)
manifier.style.backgroundPosition = `${imgLeft}px ${imgTop}px`
}
复制代码
.originImage {
background-position: center center;
background-size: contain;
background-repeat: no-repeat;
position: relative;
& > img:nth-child(1) {
width: 100%;
height: auto;
visibility: hidden;
}
& > img:nth-child(2) {
width: auto;
height: auto;
position: absolute;
left: -9999px;
top: 0;
}
.biggerImage {
position: absolute;
width: 100px;
height: 100px;
border: 1px solid #ededed;
border-radius: 10px;
cursor: none;
pointer-events: none;
}
}
复制代码
css部分有一个点须要注意,须要将鼠标放大镜的鼠标属性设置为none,即穿透效果,这样在背景原图上的移动就不会受影响。不然可能会走进鼠标放大镜区域的mouseover事件