效果展示:当用户在左侧商品栏移动鼠标时,右侧随之出现产品的放大图,并跟随左侧鼠标移动且放大产品
第一步 搭建html结构
主盒子box里面包含左侧img1商品图片、yellow遮罩层,右侧div及右侧img2商品放大图片。
仿京东手机放大效果
第二步 布局CSS样式
主盒子box相对定位,里面的盒子全部绝对定位,黄色遮罩层加opacity显示半透明效果
* {
margin: 0;
padding: 0;
}
h2 {
width: 266px;
height: 66px;
margin: 0 auto;
}
#box {
position: relative;
width: 400px;
height: 400px;
border: 1px solid #ccc;
margin: 0 100px;
}
#img1 {
width: 400px;
height: 400px;
}
#yellow {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background-color: #FEDE4F;
opacity: .5;
border: 1px solid #ccc;
cursor: move;
display: none;
}
#apt {
width: 500px;
height: 500px;
position: absolute;
left: 410px;
top: 0;
display: none;
border: 1px solid #ccc;
z-index: 999; //如果右侧还有商品详细信息介绍:价格、颜色、版本等等,必须 给右侧apt盒子加z-index提高盒子层级,覆盖商品详细信息显示
overflow: hidden;
}
#img2 {
position: absolute;
top: 0;
left: 0;
}
第三步 JS
1.注册鼠标经过和离开事件,鼠标经过商品时显示黄色遮罩层及右侧商品放大图片,离开隐藏
window.addEventListener('load', function() {
function $c(a, b) {
return a.style.display = b
}
// 给鼠标注册经过和离开事件
box.addEventListener('mouseover', function() {
$c(yellow, 'block')
$c(apt, 'block')
})
box.addEventListener('mouseout', function() {
$c(yellow, 'none')
$c(apt, 'none')
})
}
2. 注册商品栏鼠标移动事件
offset系列属性:
offsetParent:获取当前元素的定位父元素。
offsetTop :获取div元素的顶部偏移量
offsetLeft :获取div元素的左边偏移量
offsetWidth: 获取div元素的宽度,包含padding+border+内容
offsetHeight :获取div元素的高度, 包含padding+border+内容
鼠标事件对象属性:
pageX:返回鼠标指针的水平坐标,相对于文档页面
pageY:返回鼠标指针的垂直坐标,相对于文档页面
clientX:返回鼠标指针的水平坐标,相对于浏览器可视区
clientY:返回鼠标指针的垂直坐标,相对于浏览器可视区
screenX:返回鼠标指针的水平坐标,相对于电脑屏幕
screenY:返回鼠标指针的垂直坐标,相对于电脑屏幕
理解这两组属性后我们来分析, 当鼠标在移动时,如何让黄色遮罩层跟随鼠标移动?
首先肯定要得到鼠标在页面中的坐标也就是pageX和pageY,然后再得到盒子在页面中的距离也就是offsetLeft和offsetTop,相减就能得到鼠标在盒子里面的坐标。
①鼠标在盒子里面的坐标 x = pageX - 盒子.offsetLeft , y轴同理
window.addEventListener('load', function() {
function $c(a, b) {
return a.style.display = b
}
// 给鼠标注册经过和离开事件
box.addEventListener('mouseover', function() {
$c(yellow, 'block')
$c(apt, 'block')
})
box.addEventListener('mouseout', function() {
$c(yellow, 'none')
$c(apt, 'none')
})
//鼠标移动事件
box.addEventListener('mousemove', function(e) {
// 2.1计算出鼠标在盒子内的坐标
let x = e.pageX - this.offsetLeft;
let y = e.pageY - this.offsetTop;
}
②此时鼠标是在左上角,京东原版是鼠标是在最中央,所以遮罩层要走宽度的一半高度的一半才能到中央,得出遮罩层的移动距离,得到坐标后赋值给遮罩层的left和top
③遮罩层不能超出大盒子,遮罩层的MAX移动距离 = 大盒子.offsetWidth - 遮罩层.offsetWidth;
window.addEventListener('load', function() {
function $c(a, b) {
return a.style.display = b
}
// 给鼠标注册经过和离开事件
box.addEventListener('mouseover', function() {
$c(yellow, 'block')
$c(apt, 'block')
})
box.addEventListener('mouseout', function() {
$c(yellow, 'none')
$c(apt, 'none')
})
//鼠标移动事件
box.addEventListener('mousemove', function(e) {
// 2 黄色盒子跟随鼠标移动
// 2.1计算出鼠标在盒子内的坐标
let x = e.pageX - this.offsetLeft;
let y = e.pageY - this.offsetTop;
// 2.2鼠标居中 防止盒子宽高发生变化写活 遮挡层不能超出父盒子
let yellowX = x - yellow.offsetWidth / 2;
let yellowY = y - yellow.offsetHeight / 2;
// 遮挡层最大移动距离
let yellowMaxX = box.offsetWidth - yellow.offsetWidth;
let yellowMaxY = box.offsetHeight - yellow.offsetHeight;
if (yellowX <= 0) {
yellowX = 0;
} else
if (yellowX >= yellowMaxX) {
yellowX = yellowMaxX;
};
if (yellowY <= 0) {
yellowY = 0;
} else if (yellowY >= yellowMaxY) {
yellowY = yellowMaxY;
};
// 赋值
yellow.style.left = yellowX + 'px';
yellow.style.top = yellowY + 'px';
}
3.移动黄色遮罩层,右侧大图片随之移动
逻辑:左侧遮罩层移动,右侧大图片跟随移动,因为两边的宽高都不一样,所以移动的距离肯定是不同的,但是移动比例肯定是相同的,我们用此逻辑分析:
现在已知遮挡层移动距离x和遮挡层最大移动距离MaxX,大图片最大移动距离用大图片宽度减去大盒子宽度可以得出,那么大图片移动距离=遮挡层移动距离*大图片最大移动距离/遮挡层最大移动距离
我们先求出大图片最大移动距离:
// 求大图片的最大移动距离
let aptMaxX = apt.offsetWidth - img2.offsetWidth;
let aptMaxY = apt.offsetHeight - img2.offsetHeight;
// 根据公式求大图片的移动距离
let aptX = yellowX * aptMaxX / yellowMaxX
let aptY = yellowY * aptMaxY / yellowMaxY
img2.style.left = aptX + 'px';
img2.style.top = aptY + 'px';
完成效果:
为什么大图片和左边是反向移动?为什么大图片不给最大移动距离?答案在CSS中
总结:案例使用offset搭配事件对象实现了动画效果,JS要实现动画效果,三大系列offset系列、client系列、scroll系列以及事件对象必不可少,所以要多多练习。
END!