文章目录
PC端网页特效
1.元素偏移量 offset 系列
//3.返回带有定位的父亲否则返回的是bodyconsole.1og(son.offsetParent);
console.log(son.parentNode);//返回父亲是最近一级的父亲亲爸爸不管父亲有没有定位
offset 与 style 区别
案例:获取鼠标在盒子内的坐标
var box = document.querySelector('.box');
box.addEventListener('mousemove', function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
})
案例:模态框拖拽
<body>
<div class="login-header"><a id="link" href="javascript:;">点击,弹出登录框</a></div>
<div id="login" class="login">
<div id="title" class="login-title">登录会员
<span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<div class="login-input">
<label>登录密码:</label>
<input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
</div>
<!-- 遮盖层 -->
<div id="bg" class="login-bg"></div>
<script>
// 1. 获取元素
var login = document.querySelector('.login');
var mask = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var closeBtn = document.querySelector('#closeBtn');
var title = document.querySelector('#title');
// 2. 点击弹出层这个链接 link 让mask 和login 显示出来
link.addEventListener('click', function() {
mask.style.display = 'block';
login.style.display = 'block';
})
// 3. 点击 closeBtn 就隐藏 mask 和 login
closeBtn.addEventListener('click', function() {
mask.style.display = 'none';
login.style.display = 'none';
})
// 4. 开始拖拽
// (1) 当我们鼠标按下, 就获得鼠标在盒子内的坐标
title.addEventListener('mousedown', function(e) {
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
// (2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
document.addEventListener('mousemove', move)
function move(e) {
login.style.left = e.pageX - x + 'px';
login.style.top = e.pageY - y + 'px';
}
// (3) 鼠标弹起,就让鼠标移动事件移除
document.addEventListener('mouseup', function() {
document.removeEventListener('mousemove', move);
})
})
</script>
</body>
案例:仿京东放大镜
见b站pink老师P810集
鼠标经过小图片盒子, 黄色的遮挡层 和 大图片盒子显示,离开隐藏2个盒子功能
就是显示与隐藏
window.addEventListener('load', function() {
var preview_img = document.querySelector('.preview_img');
var mask = document.querySelector('.mask');
var big = document.querySelector('.big');
// 1. 当我们鼠标经过 preview_img 就显示和隐藏 mask 遮挡层 和 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';
})
// 2. 鼠标移动的时候,让黄色的盒子跟着鼠标来走
preview_img.addEventListener('mousemove', function(e) {
// (1). 先计算出鼠标在盒子内的坐标
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
// console.log(x, y);
// (2) 减去盒子高度 300的一半 是 150 就是我们mask 的最终 left 和top值了
// (3) 我们mask 移动的距离
var maskX = x - mask.offsetWidth / 2;
var maskY = y - mask.offsetHeight / 2;
// (4) 如果x 坐标小于了0 就让他停在0 的位置
// 遮挡层的最大移动距离
var maskMax = preview_img.offsetWidth - mask.offsetWidth;
if (maskX <= 0) {
maskX = 0;
} else if (maskX >= maskMax) {
maskX = maskMax;
}
if (maskY <= 0) {
maskY = 0;
} else if (maskY >= maskMax) {
maskY = maskMax;
}
mask.style.left = maskX + 'px';
mask.style.top = maskY + 'px';
// 3. 大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离
// 大图
var bigIMg = document.querySelector('.bigImg');
// 大图片最大移动距离
var bigMax = bigIMg.offsetWidth - big.offsetWidth;
// 大图片的移动距离 X Y
var bigX = maskX * bigMax / maskMax;
var bigY = maskY * bigMax / maskMax;
bigIMg.style.left = -bigX + 'px';
bigIMg.style.top = -bigY + 'px';
})
})
2.元素可视区 client 系列
client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
立即执行函数
立即执行函数 ( function(){} ) ()
或者 (function(){} () )
主要作用: 创建一个独立的作用域。里面的变量都是局部变量, 避免了命名冲突问题,
//立即执行函数:不需要调用,也可以传递参数
(function(a,b){
console.log(a);//1
console.log(a+b);//3
})(1,2);//多个立即执行函数要用分号隔开
(function(a,b){
console.log(a);//2
console.log(a+b);//5
}(2,3))
案例: 淘宝 flexible.js 源码分析
3.元素滚动 scroll 系列
scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。
案例:仿淘宝固定右侧侧边栏
<style>
.w {
width: 1200px;
margin: 10px auto;
}
.slider-bar {
position: absolute;
left: 50%;
top: 300px;
margin-left: 605px;
width: 45px;
height: 130px;
background-color: pink;
}
.header {
height: 150px;
background-color: skyblue;
}
.banner {
height: 200px;
background-color: blue;
}
.main {
height: 1000px;
background-color: green;
}
span {
display: none;
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div class="slider-bar">
<span class="goBack">返回顶部</span>
</div>
<div class="header w">头部区域</div>
<div class="banner w">banner区域</div>
<div class="main w">主体部分</div>
<script>
//注意区分pageYOffset、offsetTop前者是卷去的大小,后者是在页面中的大小
//1.获取元素
var sliderbar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
var bannerTop=banner.offsetTop;//bannerTop就是被卷去头部的大小,一定要写在外面,写在滚动事件里面会不准
var sliderbarTop = sliderbar.offsetTop-bannerTop;
var main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var mainTop = main.offsetTop;
//2.页面滚动事件 scroll
//window.pageYOffset页面被卷去的头部
//当页面快要卷去头部的时候改成固定定位
document.addEventListener('scroll',function(){
// console.log(1);
if (window.pageYOffset >= bannerTop){
sliderbar.style.position='fixed';
sliderbar.style.top=sliderbarTop+'px';
}else{
sliderbar.style.position='absolute';
sliderbar.style.top='300px';
}
if (window.pageYOffset >= mainTop){
goBack.style.display='block';
}
else{
goBack.style.display='none';
}
})
页面被卷去的头部兼容性解决方案
需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:
- 声明了 DTD,使用 document.documentElement.scrollTop
- 未声明 DTD,使用 document.body.scrollTop
- 新方法 window.pageYOffset 和 window.pageXOffset,IE9 开始支持
function getScroll() {
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
};
}
使用的时候 getScroll().left
*三大系列总结
他们主要用法:
- offset系列 经常用于获得元素位置 offsetLeft offsetTop
- client 经常用于获取元素大小 clientWidth clientHeight
- scroll 经常用于获取滚动距离 scrollTop scrollLeft
- 注意页面滚动的距离通过 window.pageXOffset 获得
mouseenter 和mouseover的区别
4.动画函数封装
动画实现原理
核心原理:通过定时器 setInterval() 不断移动盒子位置
实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意此元素需要添加定位,才能使用element.style.left
取值用offsetLeft,赋值是style.left
函数简单封装、给不同元素记录不同定时器
注意函数需要传递2个参数,动画对象和移动到的距离。
如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。
<button>点击夏雨荷才走</button>
<div></div>
<span>夏雨荷</span>
<script>
// var obj = {};
// obj.name = 'andy';
// 简单动画函数封装obj目标对象 target 目标位置
// 给不同的元素指定了不同的定时器
function animate(obj, target) {
// 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
// 解决方案就是 让我们元素只有一个定时器执行
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长值一定要写在定时器里面
//把步长值改为整数,不要出现小数问题,步长公式
var step = (target-obj.offsetLeft)/10;
step = step>0?Math.ceil(step):Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button');
// 调用函数
animate(div, 300);
btn.addEventListener('click', function() {
animate(span, 200);
})
</script>
缓动效果原理
动画函数多个目标值之间移动
可以让动画函数从 800 移动到 500。
当我们点击按钮时候,判断步长是正值还是负值
- 如果是正值,则步长 往大了取整
- 如果是负值,则步长 向小了取整
动画函数添加回调函数
动画函数封装到单独JS文件里面
因为以后经常使用这个动画函数,可以单独封装到一个JS文件里面,使用的时候引用这个JS文件即可。
- 单独新建一个JS文件。
- HTML文件引入 JS 文件。
<style>
.sliderbar {
position: fixed;
right: 0;
bottom: 100px;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
cursor: pointer;
color: skyblue;
}
.con {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 40px;
background-color: green;
z-index: -1;
}
</style>
</head>
<body>
<div class="sliderbar">
<span ><-</span>
<div class="con">问题反馈</div>
</div>
<script>
var sliderbar=document.querySelector('.sliderbar');
var con = document.querySelector('.con');
sliderbar.addEventListener('mouseenter',function(){
animate(con,-160,function(){
sliderbar.children[0].innerHTML='->';
});
})
sliderbar.addEventListener('mouseleave',function(){
animate(con,0,function(){
sliderbar.children[0].innerHTML='<-';
});
})
</script>
5.常见网页特效案例
案例:网页轮播图
<div class="focus fl">
<!-- 左侧按钮 -->
<a href="javascript:;" class="arrow-l">
<
</a>
<!-- 右侧按钮 -->
<a href="javascript:;" class="arrow-r">
</a>
<!-- 核心滚动区域 -->
<!-- 不能直接放图片,最后的滚动效果是让ul滚动的-->
<ul>
<li>
<img src="upload/focus.png" alt="">
</li><li>
<img src="upload/floor.png" alt="">
</li><li>
<img src="upload/focus.png" alt="">
</li><li>
<img src="upload/focus.png" alt="">
</li><li>
<img src="upload/focus.png" alt="">
</li>
</ul>
<!-- 小圆圈 -->
<ol class="circle">
</ol>
</div>
<script>
//1.加载页面
window.addEventListener('load',function(){
//2.鼠标经过focus时显示按钮,离开隐藏
var arrow_l = this.document.querySelector('.arrow-l');
var arrow_r = this.document.querySelector('.arrow-r');
var focus = this.document.querySelector('.focus');
var focusWidth=focus.offsetWidth;
focus.addEventListener('mouseenter',function(){
arrow_l.style.display='block';
arrow_r.style.display='block';
clearInterval(timer);
timer=null;//清除定时器变量
})
focus.addEventListener('mouseleave',function(){
arrow_l.style.display='none';
arrow_r.style.display='none';
timer = this.setInterval(function(){
//手动调用点击事件
arrow_r.click();
},2000);
})
//3.动态生成底部小圆圈
var ul = focus.querySelector('ul');
var ol = focus.querySelector('ol');
for (var i=0;i<ul.children.length;i++){
//创建一个li,给每一个li一个索引
var li = this.document.createElement('li');
li.setAttribute('index',i);
//把li插入到ol里面
ol.appendChild(li);
li.addEventListener('click',function(){
//4. 排他思想,排除所有人
for (var i=0;i<ol.children.length;i++){
ol.children[i].className='';
}
// 留下自己
this.className='current';
// 5.点击小圆圈移动图片,移动的是ul(ul带动里面的li移动),移动的距离=索引*focus大小
var index=this.getAttribute('index');
animate(ul,-focusWidth*index);
// 当点击了某个li,要把索引号给num和circle
num=circle=index;
})
}
// 把ol里面的第一个li设置类名为current
ol.children[0].className='current';
//6.克隆第一张图片li到ul最后面
var first=ul.children[0].cloneNode(true);
ul.appendChild(first);
//7.点击左右侧按钮图片滚动
var num=0;
var circle = 0;
//节流阀
var flag=true;
arrow_r.addEventListener('click',function(){
if(flag){
flag=false;
//如果走到了最后复制的一张图片,此时ul要快速复原left改为0
if (num==ul.children.length-1){
ul.style.left=0;
num=0;
}
num++;
animate(ul,-num*focusWidth,function(){
flag=true;//打开节流阀
});
//8.下面的小圆圈跟着变化,排他思想
circle++;
circle= circle==ol.children.length? 0:circle;
circleChange();
}
})
arrow_l.addEventListener('click',function(){
if(flag){
//如果走到了最后复制的一张图片,此时ul要快速复原left改为0
if (num==0){
num=ul.children.length-1;
ul.style.left=num*focusWidth;
}
num--;
animate(ul,-num*focusWidth,function(){
flag=false;
});
//下面的小圆圈跟着变化,排他思想
circle--;
circle= circle<0?ol.children.length-1:circle;
circleChange();
}
})
function circleChange(){
for (var i=0;i<ol.children.length;i++){
ol.children[i].className='';
}
// 留下自己
ol.children[circle].className='current';
}
//10.自动播放轮播图
var timer = this.setInterval(function(){
//手动调用点击事件
arrow_r.click();
},2000);
})
<\script>
节流阈
案例:返回顶部
滚动窗口至文档中的特定位置。
window.scroll(x, y)
注意,里面的x和y 不跟单位,直接写数字
//当我们点击了返回顶部模块,就让窗口滚动的页面最上方
goBack.addEventListener('click',function(){
// 里面的x,y不跟单位,直接写数字
// window.scroll(0,0)
animate(window, 0);
});
function animate(obj, target,callback) {
// 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
// 解决方案就是 让我们元素只有一个定时器执行
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长值一定要写在定时器里面
//把步长值改为整数,不要出现小数问题,步长公式
var step = (target-window.pageYOffset)/10;
step = step>0?Math.ceil(step):Math.floor(step);
if (window.pageYOffset == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// if(callback){
// callback();
// }
callback&&callback();
}
// obj.style.left = obj.window.pageYOffset + step + 'px';
window.scroll(0,window.pageYOffset + step);
}, 30);
}
案例:筋头云案例
鼠标经过某个小li, 筋斗云跟这到当前小li位置
鼠标离开这个小li, 筋斗云复原为原来的位置
鼠标点击了某个小li, 筋斗云就会留在点击这个小li 的位置
<style>
* {
margin: 0;
padding: 0
}
ul {
list-style: none;
}
body {
background-color: black;
}
.c-nav {
width: 900px;
height: 42px;
background: #fff url(images/rss.png) no-repeat right center;
margin: 100px auto;
border-radius: 5px;
position: relative;
}
.c-nav ul {
position: absolute;
}.c-nav li {
float: left;
width: 83px;
text-align: center;
line-height: 42px;
}
.c-nav li a {
color: #333;
text-decoration: none;
display: inline-block;
height: 42px;
}
.c-nav li a:hover {
color: white;
}
.c-nav li.current a {
color: #0dff1d;
}
.cloud {
position: absolute;
left: 0;
top: 0;
width: 83px;
height: 42px;
background: url(images/cloud.gif) no-repeat;
}
</style>
<script src="animate.js"></script>
<script>
window.addEventListener('load', function() {
// 1. 获取元素
var cloud = document.querySelector('.cloud');
var c_nav = document.querySelector('.c-nav');
var lis = c_nav.querySelectorAll('li');
// 2. 给所有的小li绑定事件
// 这个current 做为筋斗云的起始位置
var current = 0;
for (var i = 0; i < lis.length; i++) {
// (1) 鼠标经过把当前小li 的位置做为目标值
lis[i].addEventListener('mouseenter', function() {
animate(cloud, this.offsetLeft);
});
// (2) 鼠标离开就回到起始的位置
lis[i].addEventListener('mouseleave', function() {
animate(cloud, current);
});
// (3) 当我们鼠标点击,就把当前位置做为目标值
lis[i].addEventListener('click', function() {
current = this.offsetLeft;
});
}
})
</script>
</head>
<body>
<div id="c_nav" class="c-nav">
<span class="cloud"></span>
<ul>
<li class="current"><a href="#">首页新闻</a></li>
<li><a href="#">师资力量</a></li>
<li><a href="#">活动策划</a></li>
<li><a href="#">企业文化</a></li>
<li><a href="#">招聘信息</a></li>
<li><a href="#">公司简介</a></li>
<li><a href="#">我是佩奇</a></li>
<li><a href="#">啥是佩奇</a></li>
</ul>
</div>
移动端网页特效
1.触屏事件
触摸事件对像(TouchEvent)
因为平时我们都是给元素注册触摸事件,所以重点记住 targetTocuhes
移动端拖动元素
- touchstart、touchmove、touchend 可以实现拖动元素
- 但是拖动元素需要当前手指的坐标值 我们可以使用 targetTouches[0] 里面的pageX 和 pageY
- 移动端拖动的原理: 手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离
- 手指移动的距离: 手指滑动中的位置 减去 手指刚开始触摸的位置
拖动元素三步曲:
(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
(3) 离开手指 touchend:
注意:
手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();
<div></div>
<script>
var div = document.querySelector('div');
var startX = 0;//得到手指起始坐标
var startY = 0;
var x=0;//盒子原来位置
var y=0;
div.addEventListener('touchstart',function(e){
startX=e.targetTouches[0].pageX;
startY=e.targetTouches[0].pageY;
x=this.offsetLeft;
y=this.offsetTop;
});
div.addEventListener('touchmove',function(e){
//计算手指移动的距离:手指移动之后的坐标减去手指初始坐标
var moveX=e.targetTouches[0].pageX-startX;
var moveY=e.targetTouches[0].pageY-startY;
this.style.left=x+moveX+'px';
this.style.top=y+moveY+'px';
e.preventDefault();//阻止屏幕移动
});
</script>
2.移动端常见特效
案例:移动端轮播图
案例:返回顶部
var goBack=document.querySelector('.goBack');
var nav = document.querySelector('nav');
goBack.addEventListener('scroll',function(){
if (window.scrollY>=nav.offsetTop){
goBack.style.display='block';
}else{
goBack.style.display='none';
}
});
goBack.addEventListener('click',function(){
window.scroll(0,0);
})
classList属性
<div class="one two"></div>
<button>切换</button>
<script>
var div=document.querySelector('div');
console.log(div.classList[0]);
//1.添加类名
div.classList.add('three');//注意不加.
//2.删除类名
div.classList.remove('one');
//3.切换类名,如果存在就删除,如果没有就添加
var btn=document.querySelector('button');
btn.addEventListener('click',function(){
console.log(div.classList.toggle('bg'));
})
</script>
3.移动端常用开发插件
插件概述
1.插件的使用:1. 引入 js 插件文件。 2. 按照规定语法使用。
2.Swiper插件的使用:中文官网地址: https://www.swiper.com.cn/
3.其他移动端常见插件
superslide: http://www.superslide2.com/
iscroll: https://github.com/cubiq/iscroll
*b站pink老师P863
click 延时解决方案
移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。
解决方案:
- 禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉 300ms 的点击延迟
<meta name="viewport" content="user-scalable=no">
- 使用插件。 fastclick 插件解决 300ms 延迟。
document.addEventListener('DOMContentLoaded',function () {
/*等页面文档加载完成 不需要等所有的资源*/
FastClick.attach(document.body);
});
移动端视频插件 zy.media.js
4.移动端常用开发框架
Bootstrap
先引入jquery js文件,再引入bootstrap
MUI 原生UI前端框架
MUI 是一个专门用于做手机 APP 的前端框架。
MUI 的 UI 设计理念是:以 IOS 为基础,补充 Android 平台特有的控件。因此 MUI 封装的控件,UI 上更符合app 的体验。
MUI 中文官网地址:http://dev.dcloud.net.cn/mui/