运轮播原理结合hammer.js实现简洁的滑屏功能

不久前产生个任务,做一个非常小之h5的采取,只出2屏,需要开横向的全屏滑动切换和局部简单易行的卡通片效果,之前举行这种事物用的凡fullpage.js和jquery,性能不是坏好,于是就想协调动手来一个简易的事物来促成。最后自己之所以zepto

  • hammer.js
    和轮播的不二法门化解了是题目,效果还不易,整个页面不上马启Gzip时持有资源要的多少大小为200KB左右。这首稿子总结下者方式的实现思路。

职能演示(代码下载):

图片 1

1. 贯彻中心

1)滑屏借鉴bootstrap的carousel插件,不过了无其好复杂,只需要借鉴它的轮播实现思路即可;

2)滑屏切换的触及,跟PC不一样,PC通常都是由此元素的点击回调来点,对于滑屏的页面,完全好应用window的hashchange事件来处理,这样使经超链接装锚点或者通过js改变location.hash就可知接触切换;

3)考虑到运动还得支持手势操作,可以动用hammer.js这个手势库,API非常简单易用;

4)动画效果好据此animate.css,不过并非管其具备的代码都将至代码里,只待拷贝需要的动画片效果相关的代码即可;

5)替代jquery,首选zepto;

6)滑屏效果下transition动画,为了能够响应动画结束的回调,可以考虑采用transition.js,这个呢是Bootstrap提供的家伙,不过它们默认只能跟jquery使用,要本着她有些改变一下才会跟zepto联合使用。

这些要点说的较粗,后面的内容会相继详细介绍。

2. html结构

空的滑屏页的html结构是这么的:

<div id="container" class="container">
    <section id="page-1" class="page page--1">
    </section>
    <section id="page-2" class="page page--2">
    </section>
    <section id="page-3" class="page page--3">
    </section>
</div>

html,
body {
    height: 100%;
    -webkit-tap-highlight-color: transparent;
}

.container,
.page {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.page {
    overflow: hidden;
    display: none;
    -webkit-transition: -webkit-transform .4s ease;
    transition: transform .4s ease;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

.container与.page初始化的上以绝对定位,全屏布局。每一个section.page代表一致页,并且默认不形,所有页的原则性都同一,也就是说要持有页都显示的话,这些页会重叠在同块。

demo页的html结构是:

<div id="container" class="container">
    <section id="page-1" class="page page--1">
        <div class="page__jump"><a href="#page-2" title="">下一页</a></div>
        <p class="page__num animated">1</p>
    </section>
    <section id="page-2" class="page page--2">
        <div class="page__jump"><a href="#page-1" title="">上一页</a><a href="#page-3" title="">下一页</a></div>
        <p class="page__num animated">2</p>
    </section>
    <section id="page-3" class="page page--3">
        <div class="page__jump"><a href="#page-2" title="">上一页</a></div>
        <p class="page__num animated">3</p>
    </section>
</div>

demo相关的css就未显了。其中animated是行使animate.css需要之,animate.css是一个卡通库,github上发。

3. 滑屏切换的落实思路

滑屏切换就是经js控制2只如滑动的页长及去以下定义之及时有些css类实现之:

.page.page--active,
.page.page--prev,
.page.page--next {
    display: block;
}

.page.page--next,
.page.page--active.page--active-right {
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
}

.page.page--prev,
.page.page--active.page--active-left {
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
}

.page.page--next.page--next-left,
.page.page--prev.page--prev-right,
.page.page--active {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}

.page–active代表目前著的页,页面初始化后,通过以下js调用,给第一页加上.page—active:

var $activePage;

//初始化显示第一页
(function () {
    $activePage = $('#page-1');
    $activePage.addClass('page--active');
})();

如此页面默认就显示了第一页。以向左滑屏说明这些css的施用原理:

先是步,找到下一样页的section,添加page–next类,将她定位当前页的右边,为滑屏做准备;

仲步,找到时页的section,给其填补加page–active-left,由于这个类似改变了translate3D属性的值,所以时页会往左滑动一屏;

以次步的还要,给下一致页的section,添加page–next-left,由于这个看似改变了translate3D属性的价,所以下一页会往左滑动一屏;

老三步,在现阶段页与产一样页滑屏动画结束后,找到原来的当下页,移除掉page–active和page–active-left类;

当第三步之以,找到下一致页,移除掉page–next和page–next-left类,添加page–active。

gif图说明如下

图片 2

通向右侧滑屏原理类似

先是步,找到上一致页的section,添加page–prev类,将她定位当前页的左手,为滑屏做准备;

仲步,找到时页的section,给她填补加page–active-right,由于是类似改变了translate3D属性的值,所以时页会往右边滑动一屏;

当亚步的以,给上亦然页的section,添加page–prev-right,由于这个近乎改变了translate3D属性的值,所以上一页会往右边滑动一屏;

其三步,在当下页和达到一致页滑屏动画结束晚,找到本的目前页,移除掉page–active和page–active-right类;

当第三步之又,找到上同页,移除掉page–prev和page–prev-right类,添加page–active。

概括以上实现原理,封装成JS函数如下:

var TRANSITION_DURATION = 400, sliding = false; 

function getSlideType($targetPage) {
    var activePageId = $activePage.attr('id'),
            targetPageId = $targetPage.attr('id');
    return activePageId < targetPageId ? 'next' : activePageId == targetPageId ? '' : 'prev';
}

function slide(targetPageId) {
    var $targetPage = $('#' + targetPageId);
    if (!$targetPage.length || sliding) return;

    var slideType = getSlideType($targetPage),
            direction = slideType == 'next' ? 'left' : 'right';
    if (slideType == '') return;

    sliding = true;
    $targetPage.addClass('page--' + slideType);
    $targetPage[0].offsetWidth;
    $activePage.addClass('page--active-' + direction);
    $targetPage.addClass('page--' + slideType + '-' + direction);

    $activePage
            .one($.transitionEnd.end, function () {
                $targetPage.removeClass(['page--' + slideType, 'page--' + slideType + '-' + direction].join(' ')).addClass('page--active');
                $activePage.removeClass(['page--active', 'page--active-' + direction].join(' '));
                $activePage = $targetPage;
                sliding = false;
            })
            .emulateTransitionEnd(TRANSITION_DURATION);
}

出于$activePage在页面初始化的当儿默认指定为率先页,在历次滑屏结束晚还见面更新成为时的当下页,所以调用的上要将对象页的ID传于slide函数即可。以上代码可能会见发出疑点的凡:

1)$targetPage[0].offsetWidth的来意,这个代码用来点浏览器的重绘,因为目标页原来是display:
none的,如果非沾重绘的话,下一致步上加css类后拿看不到动画效果;

2)$.transitionEnd.end以及emulateTransitionEnd的用意,这个在产一些证实。

4. 浏览器css动画结束的回调及模拟

bootstrap提供了一个家伙,transition.js,用来判定浏览器是否支持css动画回调事件,以及当浏览器没有于动画结束晚自行触发回调的奇情况下通过模拟的主意来手动触发回调,原先是家伙只能配合jquery使用,为了在zepto中应用,必须稍微改变一下,下面就反后的代码:

(function(){
    var transition = $.transitionEnd =  {
        end: (function () {
            var el = document.createElement('transitionEnd'),
                transEndEventNames = {
                    WebkitTransition: 'webkitTransitionEnd',
                    MozTransition: 'transitionend',
                    OTransition: 'oTransitionEnd otransitionend',
                    transition: 'transitionend'
                };

            for (var name in transEndEventNames) {
                if (el.style[name] !== undefined) {
                    return transEndEventNames[name];
                }
            }
            return false;
        })()
    };

    $.fn.emulateTransitionEnd = function (duration) {
        var called = false,
            _this = this,
            callback = function () {
                if (!called) $(_this).trigger(transition.end);
            };

        $(this).one(transition.end, function () {
            called = true;
        });

        setTimeout(callback, duration);
        return this;
    };
})();

$.transitionEnd.end代表手上浏览器支持的动画结束事件之名目。$.fn.emulateTransitionEnd是一个扩展了Zepto原型的一个计,传入一个动画的联网时间,当是时段了了后,如果浏览器没有自动触发回调事件,called就一直是false,setTimeout会导致callback被调用,然后callback内部就会见手动触发动打完的回调。为什么要由此是方法来学动画结束,是因浏览器就是支持动画结束事件之回调,但是小时候并无见面接触这个波,或者当动画结束晚未可知马上触发,影响回调的准确性。传入的duration应该同实施动画的元素,在css上安的transtion-duration相同,注意以下代码中标黄的一部分:

var 

TRANSITION_DURATION =
400

;
$activePage
            .one($.transitionEnd.end, function () {
                $targetPage.removeClass(['page--' + slideType, 'page--' + slideType + '-' + direction].join(' ')).addClass('page--active');
                $activePage.removeClass(['page--active', 'page--active-' + direction].join(' '));
                $activePage = $targetPage;
                sliding = false;
            })
            .emulateTransitionEnd(TRANSITION_DURATION);

.page {
    overflow: hidden;
    display: none;
    -webkit-transition: -webkit-transform .4s ease;
    transition: transform .4s ease;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

5. hashchange事件

PC端滑屏都是让元素添加点击事件触发的,移动端可采用window的hashchange事件:

$(window).on('hashchange', function (e) {
    var hash = location.hash;
    if (!hash) hash = '#page-1';
    slide(hash.substring(1));
});

location.hash = '#page-1';

hashchange事件,在js代码中经转移loaction.hash或者是点击<a
href=”#page-2″
title=””>下一页</a>这样的超链接时,都见面接触,所以一旦以是波之回调去做滑屏切换即可。这样那些达到同页与生一样页的链接元素都休想加事件了。

6. hammer.js利用简介

hammer.js是一个手势库,支持常用的手势操作,使用简便,引入其的js之后,通过以下的方来支撑手势滑屏:

//初始化手势滑动
var container = document.getElementById('container'),
        mc = new Hammer.Manager(container),
        Swipe = new Hammer.Swipe();

mc.add(Swipe);

mc.on('swipeleft', function (e) {
    swipteTo('next', e);
});
mc.on('swiperight', function (e) {
    swipteTo('prev', e);
});

function swipteTo(slideType, e) {
    var $targetPage = $activePage[slideType]('.page');
    $targetPage.length && (location.hash = '#' + $targetPage.attr('id'));
}

将全container元素作为滑屏的stage,监听到swipeleft事件,就意味着于左滑,页面应该出示下同样页;监听到swiperight事件,就象征为右侧滑,页面应该显得下一致页。

7. 结束语

animate.css的动就不详细介绍了,比较简单,这是她的github地址:https://github.com/daneden/animate.css,是一个死好用的动画库。本文将多年来底某些办事更记录了下去,技术达到的物,有的上有的文字不可知一心讲的懂得,所以我不得不一直自己之能力去把一部分题目讲地稍微细致一点,说之怪和来问题的尽管在评论区与自说明,我会认真查看,另外自好对活动端即时同一片入门不要命,您发出重好的理念,欢迎和我们一块分享。谢谢君的阅读,马上就是新年,祝君猴年大吉!

本文源码下载

相关文章