jQuery学习笔记

基于jQuery的全屏切换插件封装

2019-01-25  本文已影响0人  小人物的秘密花园

学习资料

慕课网全屏切换效果

概述

最近在慕课网上学习奇舞团课程系列--全屏切换效果的视频课程,将学习到的知识点整理在本文中,便于以后参考;

功能点

1.支持横屏或竖屏滚动;
2.支持页签点击事件,点击页签可以向上滑动一页也可以向下滑动一页;
3.支持鼠标滚动事件,鼠标滚轮向上滚动,则向上滑动一页,反之向下滑动一页;
4.支持键盘事件,当用户按键盘的上键或左键时,实现向上滑动一页,当用户按键盘上的右键或者下键,实现向下滑动一页;

知识点

$(selector).on()

描述

在选定的元素上绑定一个或多个事件处理函数;

语法

$.on(events[,selector][data],handler(eventObject));

参数说明

绑定的事件类型,当有多个事件存在时,事件与事件之间使用空格分隔,例如click keydown;

一个选择器字符串,用于过滤出被选中元素中能够触发事件的后代元素,如果为null,那么被选中的元素总是能触发事件。

事件触发时要传给处理函数的event.data

事件触发时,执行的函数;

使用.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

过渡动画结束后调用的回调函数;

MDN transitionend
菜鸟教程

transition

动画平滑过渡,属性如下图:


image.png

transform

CSS3新增的转换模块;


image.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])

参数说明

image.png

实现思路

竖屏全屏要素

横屏全屏展示

jQuery插件封装

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)
上一篇 下一篇

猜你喜欢

热点阅读