之前做这种东西用的是fullpage.js和jquery,需要做横

选用轮播原理结合hammer.js达成简洁的滑屏功效

2016/02/02 · JavaScript · 滑屏

原稿出处: 流云诸葛   

方今有个职务,做叁个不行小的h5的运用,唯有2屏,必要做横向的全屏滑动切换和部分轻便的动漫效果,早先做这种东西用的是fullpage.js和jquery,质量不是很好,于是就想协调动手弄八个简易的东西来贯彻。最终小编用zepto

  • hammer.js 和轮播的不二法门解决了这么些主题材料,效果还不易,整个页面不开启Gzip时怀有能源央求的数额大小为200KB左右。那篇小说总计下那么些办法的落到实处思路。

功用演示(代码下载):

图片 1

新近有个任务,做一个万分小的h5的施用,独有2屏,供给做横向的全屏滑动切换和意气风发部分简易的卡通效果,在此之前做这种事物用的是fullpage.js和jquery,质量不是很好,于是就想自个儿动手弄四个粗略的事物来兑现。最终自身用zepto

1. 落到实处主旨

1卡塔 尔(英语:State of Qatar)滑屏借鉴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联合利用。

这么些要点说的一点也不细大糙,后边的剧情会挨个详细介绍。

  • hammer.js 和轮播的秘技缓慢解决了那些主题材料,效果勉强能够,整个页面不开启Gzip时具备能源诉求的数码大小为200KB左右。那篇作品总计下那几个方法的兑现思路。

2. html结构

空的滑屏页的html结构是那样的:

XHTML

<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>

1
2
3
4
5
6
7
8
<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; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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结构是:

XHTML

<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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.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'); })();

1
2
3
4
5
6
7
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函数如下:

JavaScript

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); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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卡塔 尔(英语:State of Qatar)$.transitionEnd.end以至emulateTransitionEnd的效率,这些在下局地表达。

图片 3

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; }; })();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
(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相符,注意以下代码中标黄的有的:

JavaScript

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);

1
2
3
4
5
6
7
8
9
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; }

1
2
3
4
5
6
7
8
.page {
    overflow: hidden;
    display: none;
    -webkit-transition: -webkit-transform .4s ease;
    transition: transform .4s ease;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

1. 落到实处宗旨

1卡塔 尔(英语:State of Qatar)滑屏借鉴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联合利用。

这几个要点说的比极粗糙,前面包车型客车剧情会挨个详细介绍。

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';

1
2
3
4
5
6
7
$(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>这样的超链接时,都会触发,所以黄金时代旦在这里个事件的回调去做滑屏切换就可以。那样那八个上生龙活虎页和下豆蔻梢头页的链接成分都休想加事件了。

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上有。

本文由必威发布于必威-前端,转载请注明出处:之前做这种东西用的是fullpage.js和jquery,需要做横

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。