ホームページ  >  記事  >  ウェブフロントエンド  >  モバイル Web: ページめくりシーン anime_html/css_WEB-ITnose

モバイル Web: ページめくりシーン anime_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-21 09:00:381319ブラウズ

モバイル Web、特に WeChat では、シーン アニメーションとも呼ばれるページめくりのアニメーション効果がよく見られます。

ページごとにめくると、まるで本を読んでいるような気分になります。美しい音楽とともに、各ページの内容がさまざまな 「クール」 とともに目に浮かび上がります。それ?

ここには音楽もクールな登場もなく、ただ実際にページをめくるだけです。 z

まずエフェクトを見てみましょう (表示できない場合は、以下のコードをコピーしてローカルに保存して表示します)

一生に一度です、

結婚を前提とした恋愛をしましょう。

わがままを理由に頭を下げることを拒否しなくなりました。

頑固さのために軽々しく別れることがなくなりました。

最後まで信じて、老いるまで歩き続けよう。

この世で息子の手を握り、息子と一緒に歳を重ねていけたらと願うばかりです。

あなたが永遠に生きる勇気があるなら、私は永遠に生きます。

慎重に検討した結果、私たちは

愛を継続させることにしました

ぜひ目撃してください一緒に

まずコードを貼り付けます。 参考のみ

/** * LBS slidePage 绝对定位方式 支持WP * Date: 2014-11-20 * =================================================== * opts.el 外围包裹容器/滑动事件对象(一个字符串的CSS选择器或者元素对象) * opts.index 索引(默认0) 指定显示哪个索引的页 * opts.current    当前页添加的类名(默认'current') * opts.navShow 是否需要导航指示 默认false不需要  * opts.navClass 导航指示容器的类名 方便设置样式 (默认'slide-nav')  * opts.auto 是否自动播放 默认false * opts.delay 自动播放间隔时间 默认5000(单位毫秒) 自动播放时有效 * opts.locked 是否锁定头尾滑动  默认false 如果开启则不能使用自动播放 * opts.effect 动画效果(平移=translate 缩放=scale 重叠=overlap) 默认平移 * opts.duration 动画持续时间 默认300(单位毫秒)  * opts.minScale 动画效果为缩放时的最小缩放比率(0 ~ 1) 1为没有缩放效果 默认0.5 * opts.start 手指按下时 执行函数 * opts.move 手指移动中 执行函数 * opts.end 手指收起后 执行函数 * =================================================== * this.box 包裹页的容器对象 * this.index 当前索引 * this.length 有多少页 最后一页的索引为 this.length-1 * this.play 调用自动播放的方法  * this.stop 清除自动播放的方法 * this.up 手动调用向上滑动翻页的方法 方便增加点击按钮时调用 * this.down 手动调用向下滑动翻页的方法 * =================================================== **/;(function() {    window.slidePage = function(opts) {        opts = opts || {};        if (opts.el === undefined) return;        this.box = typeof opts.el === 'string' ? document.querySelector(opts.el) : opts.el;        this.pages = this.box.children;        this.length = this.pages.length;        if (this.length < 1) return;        if (opts.index > this.length - 1) opts.index = 0;        this.body = document.getElementsByTagName('body')[0];        this.nav = null;        this.navs = [];        this.navShow = !!opts.navShow || false;        this.navClass = opts.navClass || 'slide-nav';        this.index = this.oIndex = opts.index || 0;        this.current = opts.current || 'current';        this.locked = !!opts.locked || false;        this.auto = !!opts.auto || false;        this.auto && (this.delay = opts.delay || 5000);        this.effect = opts.effect || 'translate';        this.duration = opts.duration || 300;        this.minScale = opts.minScale || 0.5;        this.start = opts.start || function() {};        this.move = opts.move || function() {};        this.end = opts.end || function() {};        this.timer = null;        this.animated = true;        this.touch = {};        this.point = '';        this.init();    };    slidePage.prototype = {        init: function() {            this.navShow && this.createNav();            this.initSet();            this.bind();        },        createNav: function() {            var li = null,                i = 0;            this.nav = document.createElement('ul');            for (; i < this.length; i++) {                li = document.createElement('li');                this.navs.push(li);                this.nav.appendChild(li);            }            this.nav.className = this.navClass;            this.body.appendChild(this.nav);        },        initSet: function() {            this.height = document.documentElement.clientHeight || document.body.clientHeight;            if (this.css(this.box, 'position') !== 'absolute' || this.css(this.box, 'position') !== 'relative') this.box.style.position = 'relative';            if (this.css(this.box, 'overflow') !== 'hidden') this.box.style.overflow = 'hidden';            this.box.style.height = this.height + 'px';            for (var i = 0; i < this.length; i++) {                if (this.css(this.pages[i], 'display') !== 'none') this.pages[i].style.display = 'none';                if (this.css(this.pages[i], 'position') !== 'absolute') this.pages[i].style.position = 'absolute';                this.pages[i].style.height = this.height + 'px';            }            if (this.navShow) {                this.nav.style.marginTop = -this.nav.offsetHeight / 2 + 'px';                this.navs[this.index].className = this.current;            }            this.pages[this.index].className += ' ' + this.current;            this.zIndex = parseInt(this.css(this.pages[this.index], 'zIndex') === 'auto' ? 1 : this.css(this.pages[this.index], zIndex)) + 10;            this.pages[this.index].style.display = 'block';        },        bind: function() {            var _this = this;            this.on(this.box, ['touchstart', 'pointerdown', 'mousedown'], function(e) {                _this.touchStart(e);                _this.auto && _this.stop();            });            this.on(this.box, ['touchmove', 'pointermove', 'mousemove'], function(e) {                _this.touchMove(e);                _this.auto && _this.stop();            });            this.on(this.box, ['touchend', 'touchcancel', 'pointerup', 'mouseup'], function(e) {                _this.touchEnd(e);                _this.auto && _this.play();            });        },        touchStart: function(e) {            this.point = e.type.indexOf('down') < 0 ? 'touch' : 'pointer';            if (this.point === 'pointer') {                this.touch.x = e.pageX;                this.touch.y = e.pageY;            }else if (this.point === 'touch') {                this.touch.x = e.touches[0].pageX;                this.touch.y = e.touches[0].pageY;            }            this.touch.disX = 0;            this.touch.disY = 0;            this.touch.fixed = '';            this.start && this.start();        },        touchMove: function(e) {            e.stopPropagation();            e.preventDefault();            if (this.point === '') return;            if (this.touch.fixed === 'left') return;            if (!this.animated) return;            if (this.point === 'pointer') {                this.touch.disX = e.pageX - this.touch.x;                this.touch.disY = e.pageY - this.touch.y;            }else if (this.point === 'touch') {                if (e.touches.length > 1) return;                this.touch.disX = e.touches[0].pageX - this.touch.x;                this.touch.disY = e.touches[0].pageY - this.touch.y;            }            if (this.touch.fixed === '') {                if (Math.abs(this.touch.disY) > Math.abs(this.touch.disX)) {                    this.touch.fixed = 'up';                } else {                    this.touch.fixed = 'left';                }            }            if (this.touch.fixed === 'up') {                if (this.effect === 'scale') {                    this.scale = ((this.height - Math.abs(this.touch.disY)) / this.height).toFixed(3);                    this.scale < this.minScale && (this.scale = this.minScale);                }                if (this.touch.disY > 0) {                    if (this.locked && this.oIndex === 0) return;                    this.dis = -this.height;                    this.index = this.oIndex - 1;                    this.index < 0 && (this.index = this.length - 1);                    if (this.effect === 'scale') this.setOrigin(this.oIndex, 'center bottom');                } else {                    if (this.locked && this.oIndex === this.length - 1) return;                    this.dis = this.height;                    this.index = this.oIndex + 1;                    this.index > this.length - 1 && (this.index = 0);                    if (this.effect === 'scale') this.setOrigin(this.oIndex, 'center top');                }                if (this.nIndex !== undefined && this.nIndex !== this.index && this.nIndex !== this.oIndex) {                    this.pages[this.nIndex].style.display = 'none';                    this.pages[this.nIndex].style.zIndex = '';                    this.pages[this.nIndex].style.webkitTransform = this.pages[this.nIndex].style.transform = '';                }                this.nIndex = this.index;                this.pages[this.oIndex].style.zIndex = this.zIndex;                this.pages[this.index].style.zIndex = this.zIndex + 10;                this.setTransform(this.index, this.dis);                this.pages[this.index].style.display = 'block';                this.setTransform(this.index, this.touch.disY + this.dis);                if (this.effect === 'translate') this.setTransform(this.oIndex, this.touch.disY);                if (this.effect === 'scale') this.setScale(this.oIndex, this.scale);                this.move && this.move();            }        },        touchEnd: function(e) {            this.point = '';            if (this.index === this.oIndex) return;            if (this.touch.fixed === 'up') {                var Y = Math.abs(this.touch.disY);                if ((this.animated && Y > 10) || Y > this.height / 2) {                    this.slide();                } else {                    this.goback();                }                this.end && this.end();            }        },        css: function(o, n) {            return getComputedStyle(o, null)[n];        },        on: function(el, types, handler) {            for (var i = 0, l = types.length; i < l; i++) el.addEventListener(types[i], handler, false);        },        setScale: function(index, v) {            this.setStyle(this.pages[index], 'transform', 'scale(' + v + ')');        },        setOrigin: function(index, dir) {            this.setStyle(this.pages[index], 'transform-origin', dir);        },        setTransform: function(index, v) {            this.setStyle(this.pages[index], 'transform', 'translate3d(0,' + v + 'px,0)');        },        setTransition: function(index, v) {            this.setStyle(this.pages[index], 'transition', 'all ' + v + 'ms');        },        setStyle: function(el, p, v) {            var prefix = ['o', 'moz', 'ms', 'webkit', ''],                i = 0,                l = prefix.length;            for (; i < l; i++) {                (function(i) {                    var s = prefix[i] + '-' + p;                    s = s.replace(/-\D/g, function(match) {                        return match.charAt(1).toUpperCase();                    });                    el.style[s] = v;                }(i));            }        },        slide: function() {            var _this = this;            this.animated = false;            this.setTransition(this.index, this.duration);            this.setTransition(this.oIndex, this.duration);            this.setTransform(this.index, 0);            if (this.effect === 'translate') this.setTransform(this.oIndex, -this.dis);            if (this.effect === 'scale') this.setScale(this.oIndex, this.minScale);            setTimeout(function() {                if (_this.index !== _this.oIndex) _this.update();                _this.animated = true;            }, this.duration);        },        goback: function() {            var _this = this;            this.setTransition(this.index, 100);            this.setTransition(this.oIndex, 100);            this.setTransform(this.index, this.dis);            if (this.effect === 'translate') this.setTransform(this.oIndex, 0);            if (this.effect === 'scale') this.setScale(this.oIndex, 1);            setTimeout(function() {                _this.clear();                _this.pages[_this.index].style.display = 'none';                _this.index = _this.oIndex;            }, 100);        },        update: function() {            if (this.navShow) {                this.navs[this.index].className = this.current;                this.navs[this.oIndex].className = '';            }            this.pages[this.oIndex].style.display = 'none';            this.pages[this.index].className += ' ' + this.current;            this.pages[this.oIndex].className = this.pages[this.oIndex].className.replace(this.current, '').trim();            this.clear();            this.oIndex = this.index;        },        clear: function() {            this.pages[this.index].style.webkitTransition = this.pages[this.index].transition = '';            this.pages[this.oIndex].style.webkitTransition = this.pages[this.oIndex].transition = '';            this.pages[this.index].style.webkitTransform = this.pages[this.index].style.transform = '';            this.pages[this.oIndex].style.webkitTransform = this.pages[this.oIndex].style.transform = '';            this.pages[this.oIndex].style.zIndex = '';            this.pages[this.index].style.zIndex = '';            if (this.effect === 'scale') this.setOrigin(this.oIndex, '');        },        animate: function() {            var _this = this;            this.setTransform(this.index, this.dis);            this.pages[this.index].style.display = 'block';            this.pages[this.oIndex].style.zIndex = this.zIndex;            this.pages[this.index].style.zIndex = this.zIndex + 10;            this.setTransition(this.index, 0);            this.setTransition(this.oIndex, 0);            setTimeout(function() {                _this.slide();            }, 50);        },        up: function() {            this.dis = this.height;            this.index++;            this.index > this.length - 1 && (this.index = 0);            if (this.effect === 'scale') this.setOrigin(this.oIndex, 'center top');            this.animate();        },        down: function() {            this.dis = -this.height;            this.index--;            this.index < 0 && (this.index = this.length - 1);            if (this.effect === 'scale') this.setOrigin(this.oIndex, 'center bottom');            this.animate();        },        play: function() {            var _this = this;            if (this.locked) return;            this.timer = setInterval(function() {                _this.up();            }, this.delay);        },        stop: function() {            this.timer && clearInterval(this.timer);            this.timer = null;        }    };}());查看完整代码

と以前も書きました 画像の切り替え 共通点が多く、全体のページめくりや画像の切り替え原理も似ています。

自動再生、3 ページめくり効果、頭尾スライド制限などをサポートします。

ページめくりアニメーションはコンテナ内でスライドするもので、このコンテナでは一度に 1 ページのみが表示され、CSS3 アニメーション効果を持ついくつかの要素が各ページに表示されます。

簡単な HTML 構造は次のとおりです。

<div id="slidePageBox" class="slide-box">    <section class="slide-page page1">         <!-- 1 -->    </section>    <section class="slide-page page2">        <!-- 2 -->    </section>    <section class="slide-page page3">        <!-- 3 -->    </section>    <section class="slide-page page4">        <!-- 4 -->    </section>    <section class="slide-page page5">        <!-- 5 -->    </section></div>

slide-box というクラス名を持つ div タグがコンテナで、slide-page というクラス名を持つセクション タグがそれぞれコンテナです。めくるページ。

this.box = typeof opts.el === 'string' ? document.querySelector(opts.el) : opts.el;this.pages = this.box.children;this.length = this.pages.length;

ここで、this.box はコンテナであり、this.pages はめくるすべてのページです。

this.height = document.documentElement.clientHeight;this.box.style.height = this.height + 'px';for (var i = 0; i < this.length; i++) {    //..    this.pages[i].style.height = this.height + 'px';}

ブラウザ ウィンドウの高さを取得し、コンテナとページの高さをこの値に設定します。このページめくりは上下にスライドしており、JSでは幅の値が取得できません。

CSS を使用してコンテナの幅は width:100% に設定され、最大幅は max-width:640px に制限されますが、実際の状況に応じて設定できます。

ここでページめくりに切り替えます。コンテナ内で指がスライドすると、指が一定距離スライドすると、コンテナから離れるとページめくりが開始されます。

タッチイベント: 指が入った、指が動いた、指が遠ざかった

ポインタイベント: ポインタが押された、ポインタが移動した、ポインタが引っ込んだ

マウスイベント: マウスが押された、マウスが移動、マウスを格納します

//..bind: function() {    var _this = this;    this.on(this.box, ['touchstart', 'pointerdown', 'mousedown'], function(e) {        _this.touchStart(e);         //..    });    this.on(this.box, ['touchmove', 'pointermove', 'mousemove'], function(e) {        _this.touchMove(e);        //..    });    this.on(this.box, ['touchend', 'touchcancel', 'pointerup', 'mouseup'], function(e) {        _this.touchEnd(e);        //..    });},//..

は、タッチ イベント、WP ポインター イベント、およびマウス イベントにバインドされています。

//..touchStart: function(e) {    this.point = e.type.indexOf('down') < 0 ? 'touch' : 'pointer';    if (this.point === 'pointer') {        this.touch.x = e.pageX;        this.touch.y = e.pageY;    }else if (this.point === 'touch') {        this.touch.x = e.touches[0].pageX;        this.touch.y = e.touches[0].pageY;    }    //..},//..

移動時(タッチ、ポインタ、マウス)の初期位置を取得

//..touchMove: function(e) {    //..    if (this.touch.fixed === 'left') return;    //..    if (this.point === 'pointer') {        this.touch.disX = e.pageX - this.touch.x;        this.touch.disY = e.pageY - this.touch.y;    }else if (this.point === 'touch') {        //..        this.touch.disX = e.touches[0].pageX - this.touch.x;        this.touch.disY = e.touches[0].pageY - this.touch.y;    }    if (this.touch.fixed === '') {        if (Math.abs(this.touch.disY) > Math.abs(this.touch.disX)) {            this.touch.fixed = 'up';        } else {            this.touch.fixed = 'left';        }    }    if (this.touch.fixed === 'up') {        //..    }},//..

移動時(タッチ、ポインタ、マウス)の移動距離を取得し、方向を判定距離に基づいて上下左右に移動しますが、ここではページをめくるために上下に移動するだけです。

//..if (this.touch.fixed === 'up') {    if (this.effect === 'scale') {        this.scale = ((this.height - Math.abs(this.touch.disY)) / this.height).toFixed(3);        this.scale < this.minScale && (this.scale = this.minScale);    }    if (this.touch.disY > 0) {        if (this.locked && this.oIndex === 0) return;        this.dis = -this.height;        this.index = this.oIndex - 1;        this.index < 0 && (this.index = this.length - 1);        if (this.effect === 'scale') this.setOrigin(this.oIndex, 'center bottom');    } else {        if (this.locked && this.oIndex === this.length - 1) return;        this.dis = this.height;        this.index = this.oIndex + 1;        this.index > this.length - 1 && (this.index = 0);        if (this.effect === 'scale') this.setOrigin(this.oIndex, 'center top');    }    if (this.nIndex !== undefined && this.nIndex !== this.index && this.nIndex !== this.oIndex) {        this.pages[this.nIndex].style.display = 'none';        this.pages[this.nIndex].style.zIndex = '';        this.pages[this.nIndex].style.webkitTransform = this.pages[this.nIndex].style.transform = '';    }    this.nIndex = this.index;    this.pages[this.oIndex].style.zIndex = this.zIndex;    this.pages[this.index].style.zIndex = this.zIndex + 10;    this.setTransform(this.index, this.dis);    this.pages[this.index].style.display = 'block';    this.setTransform(this.index, this.touch.disY + this.dis);    if (this.effect === 'translate') this.setTransform(this.oIndex, this.touch.disY);    if (this.effect === 'scale') this.setScale(this.oIndex, this.scale);    this.move && this.move();}//..移动中

動作中には多くのことが行われますが、これはプログラム全体の重要な部分です。上下に移動すると、現在表示しているページが移動します。上に移動すると、次のページの一部が表示されます。下に移動すると、前のページの一部が表示されます。

頭と尾がロックされていると、下に移動すると最初のページが移動できなくなり、上に移動すると最後のページが移動できなくなります。

opts.effect 动画效果(平移=translate 缩放=scale 重叠=overlap) 默认平移

それぞれのページめくり効果に応じた初期設定を行います(単純なパン切り替えだけであればコードを大幅に節約できます)。

//..touchEnd: function(e) {    this.point = '';    if (this.index === this.oIndex) return;    if (this.touch.fixed === 'up') {        var Y = Math.abs(this.touch.disY);        if ((this.animated && Y > 10) || Y > this.height / 2) {            this.slide();        } else {            this.goback();        }       //..    }},//..

離脱時の条件(タッチ、ポインタ、マウス)に応じてスライド切り替えを行います。

//..slide: function() {    var _this = this;    this.animated = false;    this.setTransition(this.index, this.duration);    this.setTransition(this.oIndex, this.duration);    this.setTransform(this.index, 0);    if (this.effect === 'translate') this.setTransform(this.oIndex, -this.dis);    if (this.effect === 'scale') this.setScale(this.oIndex, this.minScale);    setTimeout(function() {        if (_this.index !== _this.oIndex) _this.update();        _this.animated = true;    }, this.duration);},//..

スライド スイッチが完了すると、現在のロゴ クラス名を現在のページに追加するなど、一部の設定が更新されます。各ページの css3 アニメーション要素も、このクラス名に基づいてアニメーション効果を実行できます。

//..update: function() {    if (this.navShow) {        this.navs[this.index].className = this.current;        this.navs[this.oIndex].className = '';    }    this.pages[this.oIndex].style.display = 'none';    this.pages[this.index].className += ' ' + this.current;    this.pages[this.oIndex].className = this.pages[this.oIndex].className.replace(this.current, '').trim();    this.clear();    this.oIndex = this.index;},//..

ページを切り替えて各ページのアニメーションを実行すると、シーン全体のアニメーションがほぼ完成します。

最後に、自動再生などの簡単なものがあります。

はい、それだけです。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。