直入主题:vue项目中想做一个全屏翻滚的效果,vue-fullpage 就很不错

下面介绍vue-fullpage 的使用方法,这里封装成了vue的一个指令的形式来进行使用

1、安装vue-fullpage,最新版就可以

npm install vue-fullpage -S

 

2、入口文件main.js引入

import Vue from 'vue'
// vue全屏滚动使用
import VueFullpage from './utils/VueFullpage.js'
Vue.use(VueFullpage)

 

3、main.js同级下有文件utils/VueFullpage.js

'use strict';

var fullpage = {};
var opt = {
    start: 0,
    duration: 500,
    loop: false,
    dir: 'v',
    der: 0.1,
    movingFlag: false,
    preventWechat: false,
    needInitAfterUpdated: false,
    beforeChange: function(data) {},
    afterChange: function(data) {}
};

fullpage.install = function(Vue, options) {
    var that = fullpage;
    Vue.directive('fullpage', {
        inserted: function(el, binding, vnode) {
            var opts = binding.value || {};
            that.init(el, opts, vnode);
        },
        componentUpdated: function(el, binding, vnode) {
            if (!that.o.needInitAfterUpdated) {
                return;
            }
            var opts = binding.value || {};
            that.init(el, opts, vnode);
        }
    });

    Vue.directive('animate', {
        inserted: function(el, binding, vnode) {
            if (binding.value) {
                that.initAnimate(el, binding, vnode);
            }
        }
    });
};

fullpage.initAnimate = function(el, binding, vnode) {
    var that = fullpage;
    var vm = vnode.context;
    var aminate = binding.value;
    el.style.opacity = '0';
    vm.$on('toogle_animate', function(curIndex) {
        var parent = el.parentNode;
        while (parent.getAttribute('data-id') === null) {
            parent = parent.parentNode;
        }
        var curPage = +parent.getAttribute('data-id');
        if (curIndex === curPage) {
            that.addAnimated(el, aminate);
        }
        else {
            el.style.opacity = '0';
            that.removeAnimated(el, aminate);
        }
    });
};

fullpage.addAnimated = function(el, animate) {
    var delay = animate.delay || 0;
    el.classList.add('animated');
    window.setTimeout(function() {
        el.style.opacity = '1';
        el.classList.add(animate.value);
    }, delay);
};

fullpage.removeAnimated = function(el, animate) {
    var classes = el.getAttribute('class');
    if (classes && classes.indexOf('animated') > -1) {
        el.classList.remove(animate.value);
    }
};

fullpage.assignOpts = function(option) {
    var that = fullpage;
    var o = option || {};
    for (var key in opt) {
        if (!o.hasOwnProperty(key)) {
            o[key] = opt[key];
        }
    }
    that.o = o;
};

fullpage.initScrollDirection = function() {
    if (this.o.dir !== 'v') {
        this.el.classList.add('fullpage-wp-h');
    }
};

fullpage.init = function(el, options, vnode) {
    var that = fullpage;
    that.assignOpts(options);

    that.vm = vnode.context;
    that.vm.$fullpage = that;
    that.curIndex = that.o.start;

    that.startY = 0;
    that.o.movingFlag = false;

    that.el = el;
    that.el.classList.add('fullpage-wp');

    that.parentEle = that.el.parentNode;
    that.parentEle.classList.add('fullpage-container');

    that.pageEles = that.el.children;
    that.total = that.pageEles.length;

    that.initScrollDirection();
    window.setTimeout(function() {
        that.width = that.parentEle.offsetWidth;
        that.height = that.parentEle.offsetHeight;

        for (var i = 0; i < that.pageEles.length; i++) {
            var pageEle = that.pageEles[i];
            pageEle.setAttribute('data-id', i);
            pageEle.classList.add('page');
            pageEle.style.width = that.width + 'px';
            pageEle.style.height = that.height + 'px';
            that.initEvent(pageEle);
        }
        that.moveTo(that.curIndex, false);
    }, 0);
};

fullpage.initEvent = function(el) {
    var that = fullpage;
    that.prevIndex = that.curIndex;
    el.addEventListener('touchstart', function(e) {
        if (that.o.movingFlag) {
            return false;
        }
        that.startX = e.targetTouches[0].pageX;
        that.startY = e.targetTouches[0].pageY;
    });
    el.addEventListener('touchend', function(e) {
        if (that.o.movingFlag) {
            return false;
        }
        var dir = that.o.dir;
        var sub =
            dir === 'v' ?
            (e.changedTouches[0].pageY - that.startY) / that.height :
            (e.changedTouches[0].pageX - that.startX) / that.width;
        var der = sub > that.o.der ? -1 : sub < -that.o.der ? 1 : 0;
        // that.curIndex推迟到moveTo执行完之后再更新
        var nextIndex = that.curIndex + der;

        if (nextIndex >= 0 && nextIndex < that.total) {
            that.moveTo(nextIndex, true);
        }
        else {
            if (that.o.loop) {
                nextIndex = nextIndex < 0 ? that.total - 1 : 0;
                that.moveTo(nextIndex, true);
            }
            else {
                that.curIndex = nextIndex < 0 ? 0 : that.total - 1;
            }
        }
    });
    if (that.o.preventWechat) {
        el.addEventListener('touchmove', function(e) {
            e.preventDefault();
        });
    }
};

fullpage.moveTo = function(curIndex, anim) {
    var that = fullpage;
    var dist =
        that.o.dir === 'v' ? curIndex * -that.height : curIndex * -that.width;
    that.o.movingFlag = true;
    var flag = that.o.beforeChange(that.prevIndex, curIndex);
    if (flag === false) {
        // 重置movingFlag
        that.o.movingFlag = false;
        return false;
    }
    that.curIndex = curIndex;

    if (anim) {
        that.el.classList.add('anim');
    }
    else {
        that.el.classList.remove('anim');
    }

    that.move(dist);
    window.setTimeout(function() {
        that.o.afterChange(that.prevIndex, curIndex);
        that.o.movingFlag = false;
        that.prevIndex = curIndex;
        that.vm.$emit('toogle_animate', curIndex);
    }, that.o.duration);
};

fullpage.move = function(dist) {
    var xPx = '0px';
    var yPx = '0px';
    if (this.o.dir === 'v') {
        yPx = dist + 'px';
    }
    else {
        xPx = dist + 'px';
    }
    this.el.style.cssText +=
        '-webkit-transform:translate3d(' +
        xPx +
        ', ' +
        yPx +
        ', 0px);transform:translate3d(' +
        xPx +
        ', ' +
        yPx +
        ', 0px);';
};

if (window.Vue) {
    window.VueFullpage = fullpage;
    Vue.use(fullpage);
}
window.VueFullpage = fullpage;

export default fullpage;

View Code

 

4、vueFullPage.vue使用页

<template>
    <!-- vue全屏滚动 -->
    <!-- 使用方法:安装vue-fullpage,until中放入VueFullpage.js, main.js中引入 -->
    <!-- 如出现空白页时是因为数据还没加载完就渲染了v-fullpage,数据请求成功后在最外层加个 v-if展示判断 -->
    <div class="fullPage">
        <!-- 滚动区域容器 -->
        <div class="fullpage-container">
            <div class="fullpage-wp" v-fullpage="opts" v-if="isFullPage">
                <div class="page pageFirst">
                    <img class="pageBanner" :src="reportBg1">
                    <div class="dataCont">
                        <p>第一页</p>
                    </div>
                </div>
                <div class="page">
                    <img class="pageBanner" :src="reportBg2">
                    <div class="dataCont">
                        <p>第二页</p>
                    </div>
                </div>
                <div class="page"><img class="pageBanner" :src="reportBg3">
                    <div class="dataCont">
                        <p>第三页</p>
                    </div>
                </div>
                <div class="page"><img class="pageBanner" :src="reportBg4">
                    <div class="dataCont">
                        <p>第四页</p>
                    </div>
                </div>
            </div>
        </div>
        <!-- 滚动区域容器 -->
    </div>
</template>

<script>
    import 'vue-fullpage/vue-fullpage.css';
    import "@/assets/css/pages/fullpage.scss";
    import Vue from 'vue'
    export default {
        name: "vuefullPage",
        components: {},
        data() {
            return {
                isFullPage: true, //page里加v-if判断时避免空白页,请求接口完成后渲染页data-id按顺序排列
                opts: {
                    start: 0,
                    loop: false,
                    duration: 500,
                    stopPageScroll: true,
                    loopHorizontal: true,
                    beforeChange: function(prev, next) {},
                    afterChange: function(prev, next) {}
                },
                //上下滑动大背景
                reportBg1: require("@/assets/imgs/reportBg1.png"),
                reportBg2: require("@/assets/imgs/reportBg2.png"),
                reportBg3: require("@/assets/imgs/reportBg3.png"),
                reportBg4: require("@/assets/imgs/reportBg4.png"),
            }
        },
        mounted() {
            let that = this;
        },
        watch: {},
        methods: {}
    }
</script>
<style scoped lang="less">
    .fullpage-container {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
    }

    .fullPage {
        height: 100%;
    }
    .page {
        .dataCont {
                position: absolute;
                top: 10%;
                left: 7%;
        }
    }
</style>

View Code