基于jQuery的全屏切换插件封装
学习资料
概述
最近在慕课网上学习奇舞团课程系列--全屏切换效果的视频课程,将学习到的知识点整理在本文中,便于以后参考;
功能点
1.支持横屏或竖屏滚动;
2.支持页签点击事件,点击页签可以向上滑动一页也可以向下滑动一页;
3.支持鼠标滚动事件,鼠标滚轮向上滚动,则向上滑动一页,反之向下滑动一页;
4.支持键盘事件,当用户按键盘的上键或左键时,实现向上滑动一页,当用户按键盘上的右键或者下键,实现向下滑动一页;
知识点
$(selector).on()
描述
在选定的元素上绑定一个或多个事件处理函数;
语法
$.on(events[,selector][data],handler(eventObject));
参数说明
- events
绑定的事件类型,当有多个事件存在时,事件与事件之间使用空格分隔,例如
click keydown
;
- selector
一个选择器字符串,用于过滤出被选中元素中能够触发事件的后代元素,如果为null,那么被选中的元素总是能触发事件。
- data
事件触发时要传给处理函数的event.data
- handler(eventObject)
事件触发时,执行的函数;
使用.on()
给元素绑定事件的优点
委托事件不仅可以给未创建的后代元素绑定事件外,当需要监视很多元素的时候,委托事件的开销更小;
鼠标滚动事件
JavaScript事件有很多需要兼容的地方,鼠标滚轮事件在不同的浏览器中也存在差异特别是火狐浏览器,存在如下两种情况:
- 在火狐浏览器中给元素绑定鼠标滚轮事件,需要使用
DOMMouseScroll
;- 在其他浏览器(包括IE6在内)给元素绑定鼠标滚轮事件使用
mouseWheel
;
兼容写法:
$(document).on("mouseWheel DOMMouseScroll", handler);
怎样判断鼠标滚轮方向
在火狐浏览器中使用事件对象的
detail
属性判断,但在其他浏览器中使用事件对象的wheeldelta
属性来判断;
火狐浏览器方向判断的数值正负与其他浏览器是相反的:
在火狐浏览器中,当鼠标滚轮向下滚动时detail = 3
,向上滚动detail = -3
;
在其他浏览器中,当鼠标滚轮向下滚动时wheeldelta = -120
,向上滚动wheeldelta = 120
;
为了在开发时能够统一方向,将detail值取反:
// 绑定鼠标滚轮事件火狐是DOMMouseScroll, 其他浏览器是mouseWheel
$(selector).on('mouseWheel DOMMouseScroll', function(e) {
// 滚轮的方向,火狐的值与其他浏览器不同,添加负号来保持一致
var delta = e.originalEvent.wheelDelta || (-e.originalEvent.detail);
});
键盘事件
keydown
事件
描述
keydown事件发生在键盘的键被按下时触发;
原生JS中键盘事件的按键兼容性
原生JavaScript中判断按下哪个键是存在兼容性问题的:
- IE
只有keyCode属性;- Firefox
存在which和charCode属性;- Opera
存在keyCode和which属性等;
但在jQuery中已经解决了这个问题,jquery中通过.witch
和.keyCode
属性来确定按下了哪个键:
arrow left 37
arrow up 38
arrow right 39
arrow down 40
transitionend
过渡动画结束后调用的回调函数;
transition
动画平滑过渡,属性如下图:
![](https://img.haomeiwen.com/i2859893/d77c7c5bf58f451b.png)
transform
CSS3新增的转换模块;
![](https://img.haomeiwen.com/i2859893/44848be2e5ff5bca.png)
判断浏览器是否支持CSS的某个属性
实现思路
通过判断某个element的style中是否存在某个css属性。
实现代码
(function(temp) {
if (temp.style["transition"] !== undefined) {
return true;
}
return false;
})(document.createElement("div"));
给CSS样式添加前缀
/*
说明: 获取浏览器的前缀
实现: 判断某个元素的css样式中是否存在transition属性
参数: dom元素
返回值: Boolean 有则返回浏览器样式前缀,否则返回false
*/
var _prefix = (function(temp) {
var aPrefix = ['webkit', 'moz', 'o', 'ms'],
props = "";
for (var i in aPrefix) {
props = aPrefix[i] + "Transition";
if (temp.style[props] !== undefined) {
return "-" + aPrefix[i].toLowerCase() + '-';
}
}
return false;
})(document.createElement(pageSwitch));
animate()
jquery中实现动画的方法,当浏览器不支持transform,transition时,可以使用jquery的animate来代替这两CSS;样式实现动画
描述
根据一组CSS属性,执行自定义的动画;
语法
.animate(properties[,duration][,easing][,compelete])
参数说明
![](https://img.haomeiwen.com/i2859893/09cdaa86af0ca51c.png)
实现思路
竖屏全屏要素
- 全屏的元素及其父元素都要设置
height:100%;
- 将
html
,body
标签设置height:100%;
说明:
设置height:100%;
是为了是元素的高度跟随父元素的高度变化而变化;
html
标签也必须设置height:100%;
,原因是body
标签的高度继承于html
;
横屏全屏展示
- 设置html,body的
height:100%;
- 父元素设置
width: 400%;
(宽度 = 子页面个数 * 100%) - 子元素设置
float: left; width: 25%;
(宽度 = 100% / 子页面的个数)
jQuery插件封装
代码
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>JavaScript全屏显示效果</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="../css/index.css" />
</head>
<body>
<div id="container">
<div class="sections">
<div class="section" id="section0">
</div>
<div class="section" id="section1">
</div>
<div class="section" id="section2">
</div>
<div class="section" id="section3">
</div>
</div>
</div>
<script src="../js/jquery/jquery-3.3.1.min.js"></script>
<script src="../js/vender/pageSwitch.js"></script>
<script>
$('#container').pageSwitch({
loop: true,
duration: 200,
easing: 'cubic-bezier(.4,0,1,1)'
});
$('#container').pageSwitch("init");
</script>
</body>
</html>
CSS
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
overflow: hidden;
}
body {
font-family: Arial, "Microsoft YaHei", sans-serif;
}
#container,
.sections,
.section {
height: 100%;
position: relative;
}
.section {
background-color: #000;
background-size: cover;
background-position: 50% 50%;
text-align: center;
color: #fff;
}
#section0 {
background-image: url('../img/bg1.jpg');
text-shadow: 1px 1px 1px #333;
}
#section1 {
background-image: url('../img/bg2.jpg');
text-shadow: 1px 1px 1px #333;
}
#section2 {
background-image: url('../img/bg3.jpg');
text-shadow: 1px 1px 1px #333;
}
#section3 {
background-image: url('../img/bg4.jpg');
text-shadow: 1px 1px 1px #333;
}
.left {
float: left;
}
.pages {
position: fixed;
list-style: none;
}
.vertical.pages {
right: 10px;
top: 50%;
}
.pages.horzontal {
left: 50%;
bottom: 10px;
}
.pages li {
width: 8px;
height: 8px;
border-radius: 50%;
background: orange;
margin: 10px 5px;
cursor: pointer;
}
.pages.horzontal li {
display: inline-block;
vertical-align: middle;
}
.pages li.active {
width: 14px;
height: 14px;
border: 2px solid orangered;
background: none;
margin-left: 0;
}
JS
(function($) {
/*
说明: 获取浏览器的前缀
实现: 判断某个元素的css样式中是否存在transition属性
参数: dom元素
返回值: Boolean 有则返回浏览器样式前缀,否则返回false
*/
var _prefix = (function(temp) {
var aPrefix = ['webkit', 'moz', 'o', 'ms'],
props = "";
for (var i in aPrefix) {
props = aPrefix[i] + "Transition";
if (temp.style[props] !== undefined) {
return "-" + aPrefix[i].toLowerCase() + '-';
}
}
return false;
})(document.createElement(pageSwitch));
// 给对象添加属性和方法
var pageSwitch = (function() {
function pageSwitch(element, options) {
// 设置为true深拷贝,合并对象
this.settings = $.extend(true, $.fn.pageSwitch.defaults, options || {});
this.element = element;
// 初始化插件
this.init()
}
// 在pageSwitch原型上定义方法,让实例可以调用这些方法,带有下划线的方法是私有方法,没有下划线的是公有方法
pageSwitch.prototype = {
/* 说明: 初始化插件 */
/* 实现: 初始化DOM结构,布局,分页及绑定事件 */
init: function() {
// 缓存pageSwitch对象
var me = this;
// 初始化DOM
me.selectors = me.settings.selectors;
me.sections = me.element.find(me.selectors.sections);
me.section = me.sections.find(me.selectors.section);
// 属性初始化
me.direction = me.settings.direction == "vertical" ? true : false;
me.pagesCount = me.pagesCount();
// 索引的范围必须是在[0,me.pagesCount)之间
me.index = (me.settings.index >= 0 && me.settings.index < me.pagesCount) ? me.settings.index : 0;
// 反之鼠标滚轮快速滑动是页面滑动的太快回到第一页
me.canScroll = true;
// 横屏处理
if (!me.direction || me.index) {
me._initLayout();
}
// 是否分页操作
if (me.settings.pagination) {
me._initPaging();
}
// 初始化事件
me._initEvent();
},
/* 说明: 获取滑动页面数量 */
pagesCount: function() {
// section的个数即是页面的个数
return this.section.length;
},
/* 说明: 获取滑动的宽度(横屏滑动)或高度(竖屏滑动) */
switchLength: function() {
return this.direction ? this.element.height : this.element.width;
},
/* 说明: 向前滑动即是上一页 */
prev: function() {
var me = this;
// 大于0则执行减1操作
if (me.index > 0) {
me.index--;
} else if (me.settings.loop) { // 小于等于0并且loop:true,则索引置为最后一页
me.index = me.pagesCount - 1;
}
// 滑动页面
me._scrollPage();
},
/* 说明: 向后滑动即是下一页 */
next: function() {
var me = this;
// 小于页面数量则执行加1操作
if (me.index < me.pagesCount) {
me.index++;
} else if (me.settings.loop) {
// 大于或等于页面数量并且loop:true,则索引置为第一页
me.index = 0;
}
// 滑动页面
me._scrollPage();
},
/* 说明: 主要针对横屏情况进行布局 */
_initLayout: function() {
var me = this;
var width = (me.pagesCount * 100) + '%',
cellWidth = (100 / me.pagesCount).toFixed(2) + '%'; // toFixed(n)添加小数的位数
// 设置sections的宽度
me.sections.width(width);
// 设置section的宽度,及让其左浮动
me.section.width(cellWidth).css('float', 'left');
},
/* 说明: 实现分页的DOM结构及样式 */
_initPaging: function() {
var me = this,
pagesClass = me.selectors.page.substring(1);
me.activeClass = me.selectors.active.substring(1);
// 创建DOM结构
var pageHTML = "<ul class=" + pagesClass + ">";
for (var i = 0; i < me.pagesCount; i++) {
pageHTML += "<li></li>"
}
pageHTML += '</ul>';
me.element.append(pageHTML);
// 给第一个元素添加高亮显示
var pages = me.element.find(me.selectors.page);
me.pageItem = pages.find('li');
me.pageItem.eq(me.index).addClass(me.activeClass);
// 判断是横屏还是竖屏
if (me.direction) {
pages.addClass("vertical");
} else {
pages.addClass("horzontal");
}
},
/* 说明: 初始化插件事件 */
_initEvent: function() {
var me = this;
// 给分页元素绑定事件
me.element.on('click', me.selectors.page + ' li', function() {
me.index = $(this).index();
// 滑动页面
me._scrollPage();
});
// 绑定鼠标滚轮事件火狐是DOMMouseScroll, 其他浏览器是mouseWheel
me.element.on('mousewheel DOMMouseScroll', function(e) {
if (me.canScroll) {
// 滚轮的方向,火狐的值与其他浏览器不同,添加负号来保持一致
var delta = e.originalEvent.wheelDelta || -e.originalEvent.detail;
if (delta > 0 && ((me.index && !me.settings.loop) || me.settings.loop)) {
// 向上
me.prev();
} else if (delta < 0 && ((me.index < me.pagesCount - 1 && !me.settings.loop) || me.settings.loop)) {
//向下
me.next();
}
}
});
// 判断是否支持键盘事件
if (me.settings.kerboard) {
$(window).on('keydown', function(e) {
// 键盘值
var keyCode = e.keyCode;
if (keyCode == 37 || keyCode == 38) { // 按左键,上键
me.prev();
} else if (keyCode == 39 || keyCode == 40) { // 按右键和下键
me.next();
}
});
}
// 窗口改变事件
$(window).on('resize', function(e) {
// 获取当前页面滑动的宽度或高度
var currentLength = me.switchLength();
// 获取当前页面相对于文档的坐标值
var offset = me.settings.direction ? me.section
.eq(me.index)
.offset().top : me.section
.eq(me.index)
.offset().left;
// 若offset的绝对值值大于currentLength的一半,并且当前index小于pagesCount -1, 则me.index++
if (Math.abs(offset) > (currentLength / 2) && me.index < (me.pagesCount - 1)) {
me.index++;
}
if (me.index) {
me._scrollPage();
}
});
// transitionend
me.sections.on('transitionend webkitTransitionEnd oTransitionEnd otransitionend', function() {
me.canScroll = true;
if (me.settings.callback && $.type(me.settings.callback) == "function") {
me.settings.callback();
}
});
},
/* 说明: 滑动动画 */
_scrollPage: function() {
var me = this;
// 获取当前页面相对于offsetParent的坐标
var dest = me.section.eq(me.index).position();
if (!dest) { return; }
me.canScroll = false;
// 判断浏览器是否支持transition属性
if (_prefix) {
// 添加滑动效果
me.sections.css(_prefix + "transition", "all " + me.settings.duration + 'ms ' + me.settings.easing)
// 滑动距离:
// 竖屏 获取当前元素相对于父元素的top值
// 横屏 获取left
var translate = me.direction ? "translateY(-" + dest.top + "px)" : "translateX(-" + dest.left + "px)"
me.sections.css(_prefix + "transform", translate);
} else {
var animateCss = me.direction ? { top: -dest.top } : { left: -dest.lset }
me.sections.animate(animateCss, me.settings.duration, function() {
me.canScroll = true;
if (me.settings.callback && $.type(me.settings.callback) == "function") {
me.settings.callback();
}
});
}
// 分页样式的调整
if (me.settings.pagination) {
me.pageItem.eq(me.index).addClass(me.activeClass).siblings("li").removeClass(me.activeClass);
}
}
};
return pageSwitch;
})();
// 创建对象实例
$.fn.pageSwitch = function(options) {
// 实现链式调用
return this.each(function() {
var me = $(this),
instance = me.data("pageSwitch");
// 判断实例是否存在,不存在则创建对象,并将该对象及配置项传入
if (!instance) {
instance = new pageSwitch(me, options);
// 存放实例
me.data("pageSwitch", instance);
}
// 在外部可以通过$(selection).pageSwitch("init")
if ($.type(options) === "String") {
return instance[options]();
}
});
};
// 配置参数
$.fn.pageSwitch.defaults = {
// 选择器
selectors: {
// 父层容器
sections: '.sections',
// 页面容器
section: '.section',
// 分页容器
page: '.pages',
// 分页选中时的高亮效果
active: '.active'
},
// 页面开始的索引值
index: 0,
// 动画的效果
easing: 'ease',
// 动画执行的时间
duration: 500,
// 页面是否循环播放
loop: false,
// 是否进行分页处理
pagination: true,
// 是否触发键盘事件
kerboard: true,
// 全屏方向,横屏,竖屏
direction: 'vertical', // horizontal
// 实现滑屏动画后执行的回调函数
callback: ""
};
// 在插件内部初始化,但是这种写法需要在目标元素上添加data-pageSwitch
$(function() {
$("[data-pageSwitch]").pageSwitch();
})
})(jQuery)