学习目录
小概
三大家族(offset,scroll,client);事件对象;经典案例(商品放大镜)
1.offset scroll client 三大家族
1.1 offset家族
offset家族:获取元素;自身 的真实宽高与位置
- offsetWidth / offsetHeight: 自身真实宽高 =content + padding +border
- offsetParent :获取最近的定位父元素
- offsetLeft / Top :获取‘自身’ 左 /上 外边框 到 定位父元素 左/上 内边距距离
1.2 scroll家族
scroll家族:获取元素 ‘内容’ 的真实宽高与位置
- scrollWidth / scrollHeight:内容真实宽高
- scrollLeft / scrollTop :内容真实位置:滚动条滚动的距离
滚动条事件:onscroll
经典场景:固定导航
//1.获取元素
let topPart = document.querySelector('#topPart');
let navBar = document.querySelector('#navBar');
let mainPart = document.querySelector('#mainPart');
//2.注册事件
window.onscroll = function(){
//3.事件处理
let h = document.documentElement.scrollTop;
if(h >= topPart.offsetHeight){
navBar.style.position = 'fixed';
navBar.style.top = 0;
/* 问题:滚动得时候,底部盒子会顿闪
分析: 元素设置为固定定位之后,就会脱标。 后面得标准流就会顶上去
解决: 给后面得盒子一个margin, 撑开脱标得高度
*/
mainPart.style.marginTop = 10 + navBar.offsetHeight + 'px';
}else{
navBar.style.position = 'static';
//margin复位
mainPart.style.marginTop = '10px';
};
};
1.3 client家族
client家族 :获取元素 ‘可视区域’ 得真实宽高与位置
- clientWidth/clientHeight : ‘可视区域’得宽高
- clientLeft/clientTop : ‘可视区域’得位置 (其实就是左边框与上边框宽度)
onresize :大小变化事件
经典场景:响应式布局,横竖屏适配
window.onresize = function(){
let w = document.documentElement.clientWidth;
let h = document.documentElement.clientHeight;
if(w >= 1200){//大pc
document.body.style.backgroundColor = 'red';
}else if( w >= 992 ){
document.body.style.backgroundColor = 'orange';
}else if( w >= 768 ){
document.body.style.backgroundColor = 'yellow';
}else{
document.body.style.backgroundColor = 'green';
};
/* 横竖屏适配 */
w > h ? alert('横屏') : alert('竖屏');
};
2. 事件对象
1.事件对象 : 存储与事件触发相关得数据。 (当用户触发事件得时候,浏览器会自动捕捉鼠标坐标点/键盘按键这些信息,然后存入对象
中,称之为事件对象)
2.事件对象 由 浏览器自动声明,自动赋值。
3.用户只需要获取即可 : 给事件处理函数添加一个形参 event ev e
* 原理:浏览器自动创建事件对象之后,会在触发事件得时候通过实参方式传递给事件处理函数
了解即可: 事件对象兼容性处理
谷歌火狐: 形参e
IE8 : 全局属性 window.event
*/
2.2 事件对象三大坐标系
- screen坐标系:鼠标触发到 电脑屏幕左上角距离
- client坐标系:鼠标触发点到 页面可视区左上角距离(页面滚动了,这个坐标也会变)
3 page坐标系:最常用的坐标系:鼠标触发点到页面左/上的距离
页面元素定位就是按照这个坐标系来定位的
document.body.onclick=function(e){
console.log(e.pageX,e.pageY);
}
//div 跟随鼠标
<script>
let box =document.querySelector('#box');
//为最大的window(最大视口)绑定移动事件
window.onmousemove = function(e){
//默认元素定位参考点是左上角,如果希望鼠标在元素中心,可以减去一半宽高
box.style.left = e.pageX-box.offsetWidth/2 + 'px';
box.style.top = e.pageY-box.offsetHeight/2 + 'px';
}
</script>
2.3 案例:拖拽盒子
<style>
#father {
width: 200px;
height: 400px;
background-color: skyblue;
position: absolute;
top: 0px;
left: 0px;
margin: 50px;
}
#son {
width: 200px;
height: 100px;
background-color: hotpink;
cursor: move;
}
</style>
</head>
<body>
<div id="father">
<div id="son"></div>
</div>
<script>
/*
1.复习鼠标事件
onclick : 鼠标单击(按下+松开)
ondblclick :鼠标双击
onmouseover :鼠标移入
onmouseout :鼠标移出
onmousemove :鼠标移动
onmousedown : 鼠标按下
onmouseup : 鼠标松开
2.拖拽事件由三个部分组成
2.1 拖拽开始: 鼠标按下 onmousedown (给拖拽盒子注册)
2.2 拖拽进行 :鼠标移动 onmousemove (给拖拽的区域注册,例如页面window)
2.3 拖拽结束 :鼠标松开 onmouseup (给拖拽盒子注册)
*/
//1.获取元素
let father = document.querySelector('#father');
let son = document.querySelector('#son');
//2.注册拖拽事件
//2.1 拖拽开始: 鼠标按下 onmousedown
son.onmousedown = function (e) {
//(1)求蓝线 = 红线(e.pageX)-绿线(father.offsetLeft)
let x = e.pageX - father.offsetLeft;
let y = e.pageY - father.offsetTop;
console.log(x,y);
//2.2 拖拽进行 :鼠标移动 onmousemove
window.onmousemove = function (e) {
//(2)求黑线 = 红线(e.pgaeX) - 蓝线
let x1 = e.pageX - x;
let y1 = e.pageY - y;
/* 注意点: 元素定位是以margin左上角为参考点,如果盒子有margin,减去margin */
father.style.left = x1 - 50 + 'px';
father.style.top = y1 - 50 + 'px';
};
//2.3 拖拽结束 :鼠标松开 onmouseup
son.onmouseup = function () {
console.log('鼠标松开.拖拽结束');
//结束拖拽:清除 鼠标移动事件
window.onmousemove = null;
};
};
如果父元素存在margin,一定要在移动函数内计算father left和top时减去外边距。
3. 商城放大镜案例
需求分析:
- 鼠标移入smallBox : 显示mask盒子 和 bigBox大盒子
- 鼠标移出smallBox : 隐藏mask盒子 和 bigBox大盒子
- 鼠标移动smallBox :
3.1 mask跟随鼠标移动
3.2 鼠标在mask中心位置
3.3 mask只能在smallBox里面移动(边界检测)
3.4 大盒子中的图片bigImg对应移动
图片移动距离 = mask移动距离 * 大盒子尺寸/mask尺寸
//1.获取元素
let box = document.querySelector('#box');//父盒子 他的offsetLeft才是到屏幕距离
let smallBox = document.querySelector('#smallBox');
let bigBox = document.querySelector('#bigBox');
let mask = document.querySelector('#mask');
let bigImg = document.querySelector('#bigImg');
//2.注册事件
//1.鼠标移入smallBox : 显示mask盒子 和 bigBox大盒子
smallBox.onmouseover = function () {
mask.style.display = 'block';
bigBox.style.display = 'block';
};
//2.鼠标移出smallBox : 隐藏mask盒子 和 bigBox大盒子
smallBox.onmouseout = function () {
mask.style.display = 'none';
bigBox.style.display = 'none';
};
//3.鼠标移动smallBox
smallBox.onmousemove = function (e) {
//3.1 mask跟随鼠标移动
//蓝线 = 红线(e.pageX) - 绿色(box.offsetLeft)
let x = e.pageX - box.offsetLeft;
let y = e.pageY - box.offsetTop;
//3.2 鼠标在mask中心位置
x -= mask.offsetWidth/2;
y -= mask.offsetHeight/2;
//3.3 mask只能在smallBox里面移动(边界检测)
/*
0 <= x <= smallBox宽度-mask宽度
*/
let maxX = smallBox.offsetWidth - mask.offsetWidth;
let maxY = smallBox.offsetHeight - mask.offsetHeight;
x = x < 0 ? 0 : x;
x = x > maxX ? maxX : x;
y = y < 0 ? 0 : y;
y = y > maxY ? maxY : y;
mask.style.left = x + 'px';
mask.style.top = y + 'px';
//3.4 大盒子中的图片bigImg对应移动
bigImg.style.left = -x * bigBox.offsetWidth/mask.offsetWidth + 'px';
bigImg.style.top = -y * bigBox.offsetHeight/mask.offsetHeight + 'px';
};
</script>
css样式
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 350px;
height: 350px;
margin: 100px;
border: 1px solid #ccc;
position: relative;
}
.big {
width: 400px;
height: 400px;
position: absolute;
top: 0;
left: 360px;
border: 1px solid #ccc;
overflow: hidden;
display: none;
}
.mask {
width: 175px;
height: 175px;
background: rgba(255, 255, 0, 0.4);
position: absolute;
top: 0;
left: 0;
cursor: move;
display: none;
}
.small {
position: relative;
}
.box img {
vertical-align: top;
}
#bigBox>img {
/*是让里面的图片脱标,为的就是让里面的图片进行一个移动*/
position: absolute;
}
</style>
</head>
<body>
<div class="box" id="box">
<div class="small" id="smallBox">
<img src="images/001.jpg" width="350" alt="" />
<div class="mask" id="mask"></div>
</div>
<div class="big" id="bigBox">
<img id="bigImg" src="images/0001.jpg" width="800" alt="" />
</div>
</div>
总结
多敲多练,不多说了,我去接着肝了、