1. PC 端网页特效
1. 元素偏移量offset系列
可以动态得到该元素的位置(偏移)、大小等:
- 可以获取元素距离带有定位父元素的位置
- 获取元素自身的大小(宽度 和 高度)
- offset系列常用于获取元素位置 (但需要注意是否有带定位的父盒子)
- 注意:返回的数值不带单位
offset系列属性 | 返回 |
---|
element.offsetParent | 该元素带定位的父元素,如果父级都没有定位则返回body,与element.parentNode()亲爸爸还是有区别的 | element.offsetTop | 该元素相对带有定位父元素上方的偏移量 | element.offsetLeft | 该元素相对带有定位父元素左边框的偏移量 | element.offsetWidth | 自身包括padding + border + content的宽度,返回数值不带单位 | element.offsetHeight | 自身包括padding + border + content的高度,返回数值不带单位 |
offset 与 style 的区别
offset | style |
---|
得到 任意样式表中的 样式值 | 得到行内样式表中的样式值 | 返回数值不带单位 | 带单位的字符串 | offsetWidth 包含 padding+border+width(盒子大小) | style.width 不包含padding+border(内容大小) | offsetWidth等属性是 只读属性 | style.width 可读写属性 | 结论:想获取元素大小位置,用offset更合适(读) | 想更改元素值,需要用style改变(写) |
【案例:拖动的模态框(登录框)遮挡层 —— 可以鼠标拖动 】
var preview_img = document.querySelector('.preview_img')
var mask = preview_img.children[1]
var big = preview_img.children[2]
var bigImage = big.firstElementChild;
preview_img.addEventListener('mouseenter', function () {
mask.style.display = 'block'
big.style.display = 'block'
})
preview_img.addEventListener('mouseleave', 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;
var maskMaxX = this.offsetWidth - mask.offsetWidth;
var maskMaxY = this.offsetHeight - mask.offsetHeight;
if (maskX <= 0) {
maskX = 0;
} else if (maskX >= maskMaxX) {
maskX = maskMaxX;
}
if (maskY <= 0) {
maskY = 0;
} else if (maskY >= maskMaxY) {
maskY = maskMaxY;
}
mask.style.left = maskX + 'px';
mask.style.top = maskY + 'px';
var bigMaxX = bigImage.offsetWidth - big.offsetWidth;
var bigMaxY = bigImage.offsetHeight - big.offsetHeight;
var bigX = maskX / maskMaxX * bigMaxX;
var bigY = maskY / maskMaxY * bigMaxY;
bigImage.style.left = -bigX + 'px';
bigImage.style.top = -bigY + 'px';
})
2. 元素可视区client系列
client 翻译过来就是客户端,使用client相关属性可获取元素可视区的相关信息,动态获得该元素的边框大小、元素大小等;
client常用于检测屏幕宽度:
窗口大小变化触 resize事件,可检测屏幕宽度
window.addEventListener('resize', function(){
let w = document.documentElement.clientWidth;
console.log(w);
})
client系列属性 | 返回值 |
---|
element.clientTop | 元素上边框大小 | element.clientLeft | 元素左边框大小 | element.clientWidth | 自身包括padding+content宽度,不含border,不含单位 | element.clientHeight | 自身包括padding+content高度,不含border,不含单位 |
立即执行函数
普通函数 声明调用再执行;立即执行函数不需要调用,立刻自己执行,也可以传递参数,多个立即执行函数需要加分号;隔开
写法:第二个括号可以看做调用函数
立即函数最大的作用就是 独立创建了一个作用域
flexible.js 分析
整个js文件内部就是一个立即执行函数,不需要调用就能立即执行;
同时,由于所有独立局部变量都在该作用域中,并不会与其它引入的js文件发生命名冲突
1. (function (){})()
2. (fucntion(){}())
pageshow事件
当一条会话历史记录被执行的时候将会触发页面显示(pageshow )事件。(这包括了后退/前进按钮操作,同时也会在onload 事件触发后初始化页面时触发),根据该事件对象persisted属性可以判断是否 是 缓存中的页面触发pageshow事件,注意,这个事件是给window添加。
3. 元素滚动scroll系列
scroll 系列的相关属性可以动态获得该元素的大小、滚动距离等,当滚动条发生变化会触发滚动事件onscroll
scroll常用于获取滚动距离,监听整个页面的滚动,是给window 或document 添加scroll 事件,监听某个元素内部滚动直接给某元素加即可,不包含滚动条
scroll系列属性 | 返回值 |
---|
element.scrollTop | 返回被卷去的上侧距离,不带单位,可读写 | element.scrollLeft | 返回被卷去的左侧距离,不带单位,可读写 | element.scrollWidth | 返回内容实际宽度,不带单位(因为实际宽度可能超出限定区域,才能加滚动条,获得scroll事件) | element.scrollHeight | 返回内容实际高度,不带单位 | window.pageYOffset | 整个页面被卷去的头部)【常用返回头部案例】 | window.pageXoffset | 整个页面被卷去的左部 | document.documentElement.scrollTop | 页面滚动的头部,可读写(老写法) | document.documentElement.scrollLeft | 页面滚动的左侧,可读写(老写法) |
案例: 仿淘宝固定侧边栏
滚动到banner上边沿 侧边栏固定
滚订到main主体区域 侧边栏添加 返回头部 功能
页面被卷去的头部:window.pageYOffset
页面被卷去的左部:window.pageXOffset
var backUp = document.querySelector('.back_top');
var sideBar = document.querySelector('.side_bar');
var banner = document.querySelector('.banner');
var mainBox = document.querySelector('main');
var bannerTop = banner.offsetTop;
var mainTop = main.offsetTop;
document.addEventListener('scroll', function (e) {
if (window.pageYOffset >= mainTop){
backUp.style.display = 'block';
} else if (window.pageYOffset >= bannerTop && window.pageYOffset <= mainTop) {
sideBar.style.position = 'fixed';
sideBar.style.top = '0';
} else {
backUp.style.display = 'none';
sideBar.style.position = 'absolute';
sideBar.style.top = h + 'px';
}})
4. 动画函数封装
核心原理:通过定时器setInterval() 不断移动盒子距离
- 获得盒子当前的移动距离
- 让盒子在当前位置+1个移动距离
- 利用定时器不断重复该操作
- 加1个结束定时器的条件
- 注意:此元素需要定位,才能使用
element.stytle.left ,而且移动也不会影响其它盒子的摆放
简单动画函数封装:需要2个参数:动画对象 + 结束条件
function animate(obj, target, callback) {
var step = (target - obj.offsetLeft) / 10;
clearInterval(obj.timer)
obj.timer = setInterval(function () {
if (obj.offsetLeft == target) {
clearInterval(obj.timer)
callback && callback();
} else {
obj.style.left = obj.offsetLeft + 1 + 'px';}}, 30)}
if (step <= 1) {
obj.style.left = target + 'px';
} else {
obj.style.left = obj.offsetLeft + step + 'px';}}, 30)}
}
var div = document.querySelector('div')
animate(div, 500)
- 缓动动画:让元素的速度有所变化,最常见的就是让速度慢慢停下来(匀速动画)
原理:让盒子每次移动的距离慢慢变小,速度就会慢慢落下来 核心算法:(目标值 - 现在位置)/ 10 作为每次移动的距离步长
? (但这样其实永远也到不到终点,定时器也无法关闭,需要加判断条件)
-
动画函数添加回调函数 原理:函数A 可以作为 函数B的一个参数,当函数B执行完了,再执行函数A,这个过程就叫做回调 -
图片无缝滚动原理:在最后插入第一张图(节点的深拷贝),这样两端切换就不会有过渡问题
-
节流阀:防止轮播图连续点击造成播放过快
- 原理:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发
- 设置flag变量(相当于水龙头),先关闭水龙头,利用回调函数当动画执行完毕,再打开true
轮播图 / 焦点图
需求分析:
1. 鼠标经过轮播图 左右按钮显示轮播前后 离开隐藏
2. 鼠标点击 左右按钮 轮播图对应播放
3. 对应图片的 小圆点 index高亮
4. 鼠标放在 小圆点上 对应显示轮播图
5. 自动播放轮播图(类似于右键功能)
6. 鼠标经过轮播图,停止自动播放
图片无缝滚动原理,在最后插入第一张图(节点的深拷贝),这样两端切换就不会有过渡问题
从最后一张到第一张,可以正常轮播下一张(下一张就是第一张),再迅速跳回第一张
从第一张到最后一张,可以迅速跳到最后一张,再正常轮播上一张
window.addEventListener('load', function () {
var focusBox = document.querySelector('.focus')
var arrowR = focusBox.children[0]
var arrowL = focusBox.children[1]
var imgs = focusBox.children[2]
var dots = focusBox.children[3]
var w = focusBox.offsetWidth;
console.log(w);
console.log(focusBox.children);
focusBox.onmouseenter = function () {
arrowL.style.display = 'block'
arrowR.style.display = 'block'
clearInterval(timer)
timer = null;
}
focusBox.onmouseleave = function () {
arrowL.style.display = 'none'
arrowR.style.display = 'none'
timer = setInterval(function () {
arrowR.click();
}, 2000)
}
var len = imgs.children.length;
for (var i = 0; i < len; i++) {
let dot = document.createElement('li')
dot.setAttribute('data-index', i)
dots.appendChild(dot)
}
dots.firstElementChild.classList.add('current')
for (var i = 0; i < len; i++) {
dots.children[i].addEventListener('mouseover', function () {
for (var i = 0; i < len - 1; i++) {
dots.children[i].classList.remove('current')
}
this.classList.add('current')
index = this.getAttribute('data-index')
animateSlow(imgs, -index * w)
})
}
var li = imgs.firstElementChild.cloneNode(true)
imgs.appendChild(li)
len = imgs.children.length
var index = 0;
var dotNum = dots.children.length;
arrowL.addEventListener('click', function () {
if (index == 0) {
index = len - 1;
imgs.style.left = -index * w + 'px';
}
index--;
for (var i = 0; i < dotNum; i++) {
dots.children[i].classList.remove('current')
}
dots.children[index % dotNum].classList.add('current')
animateSlow(imgs, -index * w)
})
arrowR.addEventListener('click', function () {
if (index == len - 1) {
index = 0;
imgs.style.left = -index * w
}
index++;
for (var i = 0; i < dotNum; i++) {
dots.children[i].classList.remove('current')
}
dots.children[index % dotNum].classList.add('current')
animateSlow(imgs, -index * w)
})
var timer = setInterval(function () {
arrowR.click();
}, 2000)
})
案例:带有动画的返回顶部 window.scroll(x,y)
function animateSlow(obj, target, callback) {
clearInterval(obj.timer)
obj.timer = setInterval(function () {
var step = (target - window.pageYOffset) / 10;
if (window.pageYOffset == target) {
clearInterval(obj.timer)
callback && callback();
} else {
if (Math.abs(step) <= 1) {
window.scroll(0, target)
} else {
window.scroll(0, window.pageYOffset + step)}}}, 20)
}
animateSlow(window, 0)
2. 移动端特效
移动端浏览器兼容性较好,不需要考虑以前JS的兼容性问题,可以放心使用原生JS书写效果,但移动端也有 自己独特的地方。比如触屏事件touch,Android和IOS都有。
1. 触屏事件
-
触屏事件 touch对象代表一个触摸点,触摸点可能是一根手指或触摸笔。触屏事件可响应其对屏幕或触控板操作。常见触屏事件如下:
touch触摸事件 | 说明(都有自己各自的事件对象) |
---|
touchstart | 手指触摸到一个DOM元素时触发 | touchmove | 手指在一个DOM元素上滑动时触发,默认移动屏幕操作,e.preventDefault()阻止 | touchend | 手指从一个DOM元素上移开时触发 |
-
触摸事件对象(TouchEvent) touchEvent是一类描述手指在触摸平面的状态变化事件,这类事件用于描述一个或多个触点,使开发者可以检测触点的移动、增加和减少等,可以得到触点的坐标
触摸列表 | 说明 |
---|
touches | 正在触摸屏幕的所有手指的一个列表 | targetTouches | 正在触摸当前DOM元素上的所有手指的列表 | changedTouches | 手指状态发生了改变的列表,从无到有,从有到无的变化 |
-
案例:移动端拖动元素
- 方案1:DOM元素相对于触点坐标不变
- 方案2:DOM元素初始位置 + 触点的移动距离
2. 移动端常见特效
移动端轮播图——独特之处:
1. 无缝滚动 需要将第一张添加到最后一张后,需要将最后一张添加到第一张前,因为pc端为鼠标点击,可以实现快速跳转,但是移动端为触摸点拖动,来不及快速跳转
图片编号: 3 1 2 3 1
索引编号: -1 0 1 2 3
2. .focus ul {width: 500%; }
移动端有个很大的问题,宽度是根据父元素确定的,当上面ul的宽度为 500% 时,
ul li img 继承的宽度也是 500% ,不是我们想要的效果
所以需要给 li 限制宽度,li继承ul, 所以li 的 width 为 1/5* 100%
3. 因为移动端没有兼容的问题,可以放心使用css3,所以不需要麻烦js动画函数
可以直接用过渡效果 transition: all .3s
但播放到最后一张要实现快速跳转 需要监听过渡完成事件 transitionend
4. 当前小圆点有单独的样式属性 定义在current类,可以通过切换类实现点击小圆点current
element.classList.toggle('className');
for (var i = 0; i < dots.length; i++) {
dots[i].classList.remove('current')}
ol.querySelector('.current').classList.remove('current')
ol[index].classList.add('current')
5. 手指滑动轮播图:本质就是ul跟随手指移动,简单来说就是移动端拖动元素
设置一个 标准 滑动距离超过则上/下一张, 不超过则恢复
由于小圆点对应高亮显示代码由transitionend事件触发
index只能取 0,1,2,而实际上index可以取 -1,0,1,2,3
所以在触点离开事件里,还需要当 index=3 取 0 index=-1 则取 2
瀑布流 实现原理
多行等宽元素排列,后面的元素依次添加到其后。
即:等宽不等高,图片按比例缩放至设定宽度,依次往后追加
注意:
1. 第二行 并不是按照左对齐一次排放的,而是会插入第一行所有列高度最小的元素下方
2. 父元素清除浮动,高度取列表数组的最大值
3. 移动端常用开发插件
移动端要求是快速开发,所以经常需要借助一些插件。
js插件就是js文件,它遵循一定规范编写,方便程序展示效果,拥有特定功能且方便调用,如轮播图和瀑布流插件
特点:一般是为了解决某个问题存在的,功能单一,文件小
click 延时解决方案
移动端click事件会有 300ms 的延时,原因是移动端双击会缩放(double tap to zoom)页面
解决方案:
1. 禁用缩放:<meta name="viewport" content="user-scable=no">
2. 利用touch事件自己封装这个事件解决300ms延时
1. 记录首次触摸屏幕时间
2. 记录离开屏幕时间 减去 获得 2次触摸间隔
3. 间隔时间小于150ms,并且没有滑动屏幕,则定义为点击
3. fastclick插件:网址:https://github.com/ftlabs/fastclick
2. 利用touch事件自己封装这个事件解决300ms延时 1. 记录首次触摸屏幕时间 2. 记录离开屏幕时间 减去 获得 2次触摸间隔 3. 间隔时间小于150ms,并且没有滑动屏幕,则定义为点击 3. 移动端要求是快速开发,所以经常需要借助一些插件 js插件就是js文件,它遵循一定规范编写,方便程序展示效果,拥有特定功能且方便调用,如轮播图和瀑布流插件 特点:一般是为了解决某个问题存在的,功能单一,文件小 网址:https://github.com/ftlabs/fastclick
1. Swiper插件的使用
1. 引入插入相关文件
2. 按照规定的语法使用
3. 使用方法:https://www.swiper.com.cn/usage/index.html
4. 注意不要更改里面的结构和类名,不然css和js都要对应更改,较为麻烦
2. TouchSlide/superslide插件
TouchSlide 是纯javascript打造的触屏滑动特效插件,面向手机、平板电脑等移动终端,
能实现触屏焦点图、触屏Tab切换、触屏多图切换等常用效果。
插件开源、体积小、简单实用、功能强大,是你架构移动终端网站的重要选择!
3. zy.media.js
H5 提供 video 标签,但浏览器的支持情况不同
不同视频格式文件,可以通过source解决
但是外观样式、还有 暂停、播放、全屏等功能只能自己写代码解决
可以通过插件方式制作
插件使用总结
- 确认插件实现的功能
- 去官网查看使用说明
- 下载插件
- 打开demo实例文件,查看需要引入的相关文件,并引入
- 分别复制demo实例文件中的html、css和js代码
4. 移动端常用开发框架
什么是框架:顾名思义就是一套架构,基于自身的特点向用户提供一套完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。
前端常用框架:bootstrap 、Vue 、Angular 、React 等,既能开发PC端,也能开发移动端 前端常用移动端插件:swiper 、superslide 、iscroll 等
总结:框架大而全,一整套解决方案;插件小而专一,某个功能的解决方案
jQuery
jQuery是JavaScript库,是封装好的特定的函数或方法的集合,比如获取元素、animate、hide、show等
作用:优化DOM操作,事件处理,动画设计和Ajax交互
原生JavaScript(楼梯)—— Jquery(电梯)
特点:轻量级、跨浏览器兼容、支持插件扩展,免费开源,链式编程、隐式迭代
使用css选择器选取元素,作为为客户端脚本库,可以和Ajax一起使用。简写为$符号 ,
注意:Jquery对象只能使用Jquery方法,DOM对象只能使用JS原生方法,不能混用,因为互不认识,jQuery用$() 将DOM对象以伪数组的形式 封装为jQuery对象。但二者之间需要转换,因为jQuery毕竟只封装了常用的、使用频率高的DOM方法,所以还有用原生DOM API的需求。
基础语法:$(selector).action()
入口函数
1. $(function(){
--- jQuery functions go here ----
})
2. $(document).ready(function(){
--- jQuery functions go here ----
});
DOM对象转换为jQuery对象:$(DOM对象)
jQuery对象转换为DOM对象:$('jQuery对象')[index] $('jQuery对象').get(index)
JQuery常用API
1. 选取元素:$("css选择器")
2.样式操作 $("css选择器").css("属性", "属性值") $("div").css("color", "pink")
隐式迭代:Jquery对象以伪数组的形式存储DOM元素,其遍历内部DOM的过程叫做隐式迭代
简单理解:jQuery会给匹配到的所有元素进行遍历循环,执行对应的方法,不用我们手动循环伪数组
3. 筛选选择器:类似于css的 结构为类选择器 E:nth-child(n)
4. 筛选方法:parent(亲爸爸) children(亲儿子) parents(列祖列宗) find(后代) siblings(兄弟们) eq(第几个)
5. 排他思想
先设置自己的样式A,再设置其它兄弟的样式B
$('button').mouseover(function () {
$(this).css('backgroundColor', '#f5f5f5');
$(this).siblings().css('backgroundColor', '#fff')
});
6. 链式编程(yyds)
$('button').mouseover(function () {
$(this).css('color', '#f5f5f5').siblings().css('color', '#fff')
});
6. 得到当前元素的索引号 $(this).index() 这个太棒了!!!可以做选项卡tab栏标签和内容对应切换案例
7. JQuery效果:
显示/隐藏/切换 show([speed],[callback]) hide() toggle()
淡入/淡出 fadein([speed],[callback]) fadeout() fadeToggle()
上拉/下拉 slideUp([speed],[callback]) slideDwon() slideToggle()
动画 animate({params},speed,callback)
动画和效果的区别,动画的父亲要加定位,因为有位置的偏移,效果只是一种transition过渡罢了
stop() 方法用于停止动画或效果事件的排队,清空队列,防止短时间多次触发导致效果反复执行情况产生
8. 属性操作
1. prop设置/获取属性
$('input').prop('checked', 'true')
$('input').prop('checked')
2. attr设置/获取属性
$('input').attr('data-index', '1')
$('input').attr('data-index')
2. data数据缓存 方法里的数据是放在元素的内存里面的,也可以获取自定义属性
$('span').data("uname", "andy")
9. 内容文本值
html() 获取元素内容 相当于 innerHTML
html('内容') 设置内容
text() 相当于innerText 只想得到文本
text('内容')
$('input').val() 获取表单元素的值
10. 元素操作
主要是遍历、创建、添加、删除元素操作(增删查改)
1. 遍历
$(selector).each(function(index, domEle){}) 具体理解看我另一篇文章
$.each(arr, function(index, value){}) 主要用于遍历数据、处理数据、对象,全能王
2. 添加元素
append() prepend() - 子元素添加 before() after() - 兄弟元素添加
|