<!-- PC端网页特效 -->
<!-- 元素偏移量offset系列 -->
<!-- offset翻译过来就是偏移量的意思,使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等 -->
<!-- 获得的元素距离带有定位的父元素的位置 获得元素自身的大小(宽高) 注意:!!返回的数值都不带单位 -->
<!-- 常用属性:element.offsetParent返回作为该元素带有定位的父级元素 如果父级元素都没有定位则返回body element.offsetTop返回元素相对带有父元素上方的偏移 element.offsetLeft返回元素相对带有父元素左边框的偏移 element.offsetWidth返回自身包括padding、边框、内容区的宽度,返回数值不带单位 elemen.offsetHeight返回自身包括padding、边框、内容区的高度,返回数值不带单位 -->
<!-- <div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
console.log(father.offsetTop); //100
console.log(son.offsetTop); //0
console.log(son.offsetLeft); //50
console.log(father.offsetWidth); //包括padding、边框
console.log(son.offsetParent); //返回father(要带定位,没有定位就返回body)
console.log(son.parentNode); //返回亲爸爸,无论有没有定位
</script> -->
<!-- offset与style的区别 -->
<!-- offset可以得到任意样式表的样式值,style只能得到行内样式表的值;
offset系列获取到数值是没有单位的,style获取到是带有单位的字符串;
offsetWidth包含padding、边框和宽度,style不包含
offsetWidth等属性是只读属性,只能获取不能赋值,style是可读写属性,可以获取也可以赋值
所以,我们想要获取元素大小位置用offset更合适,想要给元素更改值,则需要使用style -->
<!-- 案例:获取鼠标在盒子内的坐标 -->
<!-- 分析:1.在盒子内点击,想要得到盒子左右的距离 2.首先获得鼠标在页面中的坐标(用e.pageX,e.pageY) 3.其次得到盒子在页面中的距离(box.offsetTop,box.offsetLeft) 4.用鼠标距离页面的坐标减去盒子在页面中的距离,得到鼠标在盒子内的坐标 5.如果想要移动一下鼠标,就要获取最新坐标,使用鼠标移动事件-->
<!-- <div class="box" style="width: 200px;height:200px;background-color:aqua;"></div>
<script>
var box=document.querySelector('.box');
box.addEventListener('mousemove',function(e){
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
box.innerHTML = 'x坐标为'+x+'y坐标为'+y;
})
</script> -->
<!-- 元素可视区 client 系列 -->
<!-- client 翻译过来就是客户端、可视区的意思,使用client可以获取元素可视区的相关信息,可以得到元素的边框大小、元素大小等 -->
<!-- element.clentTop返回元素上边框大小
element.clientLeft返回元素左边框大小
element.clientWidth 返回自身包括padding、内容区的宽度,!不含边框!返回数值不带单位
element.clientHeight 返回自身包括padding、内容区的高度 ,不含边框!返回数值不带单位-->
<!-- 立即执行函数:不需要调用,立马能自己执行的函数 -->
<!-- <script>
//写法
//(function(){}()) 或者 (function(){})()
(function(){
console.log(1); //1
})();//当有多个立即执行函数时,要用分号隔开,否则会报错
//立即执行函数也可以传递参数
(function sum(a,b){ //也可以给函数取名
console.log(a+b); //3
}(1,2))//第二个小括号可以看成调用函数的意思,参数写在里面
//主要作用:创建一个独立作用域,避免了命名冲突问题,因为每个立即执行函数里的变量都是局部变量
</script> -->
<!-- 像素比:dpr(pc端为1,移动端为2) -->
<!-- resize 重新设置字体大小
pageshow 是我们重新加载页面触发的事件 -->
<!-- <script>
window.addEventListener('pageshow',function(){ //pageshow和load差不多,只是load在火狐中有一个历史页面缓存,当回退页面时不会重新缓存,而pageshow可以每次都重新缓存
alert(1);
})
</script>
-->
<!-- 元素滚动 scoll 系列 -->
<!-- scroll翻译过来就是滚动的,使用scroll系列的相关属性可以动态地得到该元素的大小、滚动距离等 -->
<!-- scroll常用属性:1.element.scollTop 返回被卷去的上侧距离,返回数值不带单位 2.element.scollLeft 返回被卷去的左侧距离,返回数值不带单位 3.element.scollWidth返回自身实际宽度(内容宽度),包括paddind,不包括边框,返回数值不带单位 4.element.scollHeight 返回自身实际高度(内容高度),包括paddind,不包括边框,返回数值不带单位 -->
<!-- 与client的区别是client返回盒子宽高,scroll返回内容宽高(内容有可能超出盒子) -->
<!-- <div style="width: 200px;height:150px;background-color:aqua;overflow: auto;">
我是内容<br>
我是内容<br>
我是内容<br>
我是内容<br>
我是内容<br>
我是内容<br>
我是内容<br>
我是内容<br>
我是内容<br>
</div>
<script>
var div = document.querySelector('div');
div.addEventListener('scroll',function(){
console.log(div.scrollTop); //返回内容超出的部分
})
</script> -->
<!-- mouseenter事件和mouseover事件的区别 !!经典面试题!⭐-->
<!-- 当鼠标移动到元素上时就会触发mouseenter事件,它类似于mouseover ; 但它们有区别:mouseover鼠标经过自身盒子会触发,经过子盒子也会触发,而mouseenter只会经过自身盒子触发
之所以会这样:是因为mouseenter不会冒泡 -->
<!-- 跟mouseenter搭配的事件,鼠标离开事件mouseleave 同样不会冒泡 -->
<div class="father" style="width: 200px;height:200px;background-color:blue;">
<div class="son" style="width:100px;height:100px;background-color:aqua;"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('mouseenter',function(){
console.log(1); //只有经过父盒子时才打印出1,经过子盒子时没有打印
})
father.addEventListener('mouseover',function(){
console.log(2); //经过父盒子和子盒子时都打印了2
})
</script>
案例:
<!-- 案例:点击后弹出模态框,有一个背景层,模态框可以拖动 -->
<!-- 分析: 1.点击弹出层,会弹出模态框,并且显示灰色透明的遮挡层(display:block) 2.点击关闭按钮,可以关闭模态框,并且同时关闭灰色半透明遮挡层(display:none) 3.鼠标放到模态框最上面一行,可以按住鼠标拖拽模态框在页面中移动 (鼠标拖拽事件:鼠标按下mousedown,鼠标移动mousemove,鼠标松开mouseup),鼠标移动模态框被拖拽过程就是不断获取坐标值赋值给模态框的left和top值(模态框能被拖拽的只有id为title那一块),鼠标的坐标减去鼠标在盒子内的坐标才是模态框真正的坐标(鼠标在拖拽模态框时,鼠标在盒子内的坐标是不变的) 4.鼠标松开,可以停止模态框移动-->
<style>
*{
padding:0 ;
margin: 0;
}
.login-header{
width: 100%;
text-align: center;
height: 30px;
font-size: 24px;
line-height: 30px;
}
.login{
display: none;
width: 500px;
height: 300px;
position: fixed;
border: 1px solid #ebebeb;
left: 50%;
top: 50%;
background: #ffffff;
box-shadow: 0px 0px 20px #ddd;
z-index: 9999; /*层叠属性,可以覆盖比它低的元素 */
transform: translate(-50%,-50%);/*将元素移动到中间位置 */
}
.login-title{
width: 100%;
margin: 10px 0px 0px 0px;
text-align: center;
line-height: 40px;
font-size: 18px;
position: relative;
cursor: move;
}
.login-input-content{
margin-top: 20px;
}
.login-button{
width: 50%;
margin: 30px auto 0px auto;
line-height: 40px;
border: 1px solid #ebebeb;
font-size: 14px;
}
.login-bg{
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, 0.3);
}
a{
text-decoration: none;
color: #000000;
}
.login-button a{
display: block;
text-align: center;
}
.login-input .list-input{
float: left;
line-height: 35px;
height: 35px;
width: 350px;
border: 1px solid #ebebeb;
text-indent: 5px;/* 缩进 */
}
.login-input{
overflow: hidden;/* 溢出隐藏*/
margin: 0px 0px 20px 0px;
}
.login-input label{
float: left;
width: 90px;
padding-right: 10px;
text-align: right;
line-height: 35px;
height: 35px;
font-size: 14px;
}
.login-title span{
position: absolute;
font-size: 12px;
right: -20px;
top: -30px;
background: #ffffff;
border: 1px solid #ebebeb;
width: 40px;
height: 40px;
border-radius: 20px;
}
</style>
</head>
<body>
<div class="login-header"><a href="javascript:;" id="link">点击,弹出登录框</a></div>
<div class="login">
<div class="login-title" id="title">
登录会员
<span>
<a href="javascript:void(0);" class="close-login" id="closeBtn">关闭</a>
</span>
</div>
<div class="login-input-content">
<div class="login-input">
<label for="">用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<div class="login-input">
<label for="">登录密码:</label>
<input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div class="login-button" id="loginBtn"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
</div>
<!-- 遮盖层 -->
<div class="login-bg" id="bg"></div>
<script>
var login = document.querySelector('.login');
var bg = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var closeBtn = document.querySelector('#closeBtn');
var title = document.querySelector('#title');
//点击弹出层,显示模态框和遮盖层
link.addEventListener('click',function(){
bg.style.display = 'block';
login.style.display = 'block';
})
//点击关闭按钮,隐藏模态框和遮盖层
closeBtn.addEventListener('click',function(){
bg.style.display = 'none';
login.style.display = 'none';
})
//鼠标一按下,获得鼠标坐标(移动事件写到按下事件里)
title.addEventListener('mousedown',function(e){
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
document.addEventListener('mousemove',move)
function move(e){
login.style.left = e.pageX - x + 'px'; //在拖拽时盒子的距离就变了,但鼠标离盒子的距离没变,可以这样求
login.style.top = e.pageY - y +'px'; //注意:!!这里为什么不直接用offsetLeft或者offsetTop来得到盒子的距离?因为offset系列的属性只能获得值不能赋值,而在这里我们需要不断给盒子赋予新的模态框的距离值,所以不能直接使用offset,只能使用style
}
//鼠标弹起,解除鼠标移动事件
document.addEventListener('mouseup',function(){
document.removeEventListener('mousemove',move);
})
})
</script>
</body>
<!-- 案例:仿京东放大镜 -->
<!-- 分析:1.整个案例可以分成三个模块 2.鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开则隐藏 3.黄色的遮挡层跟随鼠标功能 4.移动黄色遮挡层,大图片跟随鼠标移动功能 -->
<style>
.preview_img{
height: 400px;
width: 400px;
position: relative;
border: 1px solid #ccc;
}
.mask{
width: 300px;
height: 300px;
background: #FEDE4F;
opacity: .5; /* 表示半透明*/
position: absolute;
top: 0px;
left: 0px;
border: 1px solid #ccc;
cursor: move;
display: none;
}
.big{
width: 500px;
height: 500px;
position: absolute;
top:0px;
left: 410px;
background-color: antiquewhite;
border: 1px solid #ccc;
overflow: hidden;
display: none;
}
.big img{
position:absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<div class="preview_img">
<img src="../image/s3.png" alt="">
<div class="mask"></div>
<div class="big">
<img src="../image/big.jpg" alt="" class="bigImg">
</div>
</div>
</body>
js文件:
window.addEventListener('load',function(){ //先写加载完毕后再执行js代码
var preview_img = document.querySelector('.preview_img');
var mask = document.querySelector('.mask');
var big = document.querySelector('.big');
//鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开则隐藏
preview_img.addEventListener('mouseover',function(){
mask.style.display = 'block';
big.style.display = 'block';
})
preview_img.addEventListener('mouseout',function(){
mask.style.display = 'none';
big.style.display = 'none';
})
//黄色的遮挡层跟随鼠标功能
preview_img.addEventListener('mousemove',function(e){
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var maskX = x - mask.offsetWidth/2;//减去盒子宽度的一半是为了让鼠标对齐盒子最中央
var maskY = y - mask.offsetHeight/2;
if(maskX <=0){
maskX = 0;
}else if(maskX >= preview_img.offsetWidth - mask.offsetWidth){
maskX = preview_img.offsetWidth - mask.offsetWidth; //判断mask是否全在小盒子里面,如果超出则定死位置,不让他往外移动(left值小于0则定在0的位置,如果大于外盒子和mask之间的距离,则等于这个距离)(外盒子和;mask的距离是小图片盒子的宽度减去mask遮挡层的宽度)
}
if(maskY <=0){
maskY = 0;
}else if(maskY >= preview_img.offsetHeight - mask.offsetHeight){
maskY = preview_img.offsetHeight - mask.offsetHeight; //高度同理
}
mask.style.left =maskX +'px';
mask.style.top = maskY +'px';//别忘了单位px
//移动黄色遮挡层,大图片跟随鼠标移动功能
//因为大图片盒子宽高与小盒子遮挡层不同,所以移动距离也不同,可以利用比例来做,根据小图片遮挡层移动距离和小图片遮挡层最大移动距离的比值等于大图片移动距离和大图片最大移动距离的比值相同来做
//可以得出公式,小图片遮挡层移动距离*大图片最大移动距离/小图片遮挡层最大移动距离 = 大图片移动距离
var bigImg = document.querySelector('.bigImg');
var maskMax = preview_img.offsetWidth - mask.offsetWidth;
var bigMax = bigImg.offsetWidth - big.offsetWidth;
var bigX = maskX * bigMax / maskMax;
var bigY = maskY * bigMax / maskMax;
bigImg.style.left = -bigX + 'px'; // 注意!大图片是跟小图片相反移动的
bigImg.style.top = -bigY + 'px';
})
})
<!-- 案例:仿淘宝固定右侧侧边栏 -->
<!-- 1.原先侧边栏是绝对定位 2.当页面滚动到一定位置时,侧边栏改为固定定位 3.页面继续滚动,会让返回顶部这个内容显示出来 -->
<!-- 案例分析:1.需要用到页面滚动事件scroll,因为是页面滚动,所以事件源是document 2.滚动到某个位置,就是判断页面被卷去的上部值 3.页面被卷去的头部,可以通过window.pageYOffset获得 如果是被卷去的左侧就用window.pageXOffset 4.注意:!元素被卷去的头部是element.scollTop(元素里的内容被卷去),这里是页面被卷去头部,所以这里要用window.pageYOffset !ie9才开始支持 -->
<style>
.header{
width: 1000px;
height: 200px;
background-color: aqua;
margin: 10px auto;
}
.banner{
width: 1000px;
height: 500px;
margin: 10px auto;
background-color: aquamarine;
}
.main{
width: 1000px;
margin: 10px auto;
height: 800px;
background-color: blueviolet;
}
.slider-bar{
position: absolute;
left: 533px;
top: 300px;
margin-left: 600px;
width: 40px;
height: 130px;
background-color: blue;
}
span{
display: none;
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div class="slider-bar">
<span class="goback">返回顶部</span>
</div>
<div class="header">头部区域</div>
<div class="banner">banner区域</div>
<div class="main">主体部分</div>
<script>
var sliderbar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
var bannerTop = banner.offsetTop;
var sliderbarTop = sliderbar.offsetTop - bannerTop; //计算定位盒子原始的距离(它自己距离页面的距离减去banner距离页面上的距离)
var main = document.querySelector('.main');
var goback = document.querySelector('.goback');
var mainTop = main.offsetTop;
document.addEventListener('scroll',function(){
console.log(window.pageYOffset); //到banner时被卷去距离为222
if(window.pageYOffset >=bannerTop){ //大于banner的距离上面页面的距离时改为固定定位
sliderbar.style.position = 'fixed';
sliderbar.style.top = sliderbarTop +'px';
}else{
sliderbar.style.position = 'absolute';
sliderbar.style.top = '300px';
}
if(window.pageYOffset >=mainTop){ //大于main的距离上面页面的距离时显示返回顶部
goback.style.display = 'block';
}else{
goback.style.display = 'none';
}
})
</script>
</body>