我应该如何为一个带有DOM元素的东西创建一个包?

时间:2018-04-01 14:30:29

标签: javascript ecmascript-6

我已经编写了第一段代码,我认为它实际上可以重用并且可能对其他人有用。代码是一些css,一些javascript类和一些js函数。

要使用该软件包,请设置一些HTML,然后传递html元素和可选参数,例如:

dom = new DOM(document.getElementById('fullScreenWrapper'), 175),

我想以某种方式打包它,以便你基本上包含一个js文件,一个css文件,然后你可以在任何项目中使用它。 jQuery有一个扩展自己的设计模式,但我不使用jQuery。对于像这样的东西,有没有最佳实践?

这是模型,未打包:

<html>
<head>
    <style>
        /* specific styles */
        &:root {--scrollPosition:0}
        .flicWrapper{
            height: calc(var(--wrapperHeight));
        }
        .flicWrapper .flicChild{
            top: calc(var(--previousHeight));
            position: fixed;
        }
        .flicWrapper.transition{
            height: initial;
        }
        .flicWrapper.transition .flicChild{
            transition: transform .3s cubic-bezier(0, 0, 0.25, 1);
        }
        .flicWrapper .before{
            transform: translate3d(0,calc((var(--previousHeight)*-1)),0);   
        }
        .flicWrapper .active{
            transform: translate3d(0, calc((var(--previousHeight)*-1) + var(--stickyScrollPosition)), 0);
        }
        .flicWrapper .next{
            transform: translate3d(0, calc(var(--scrollPosition)), 0);
        }


        /*custom style*/
        body{
            margin: 0;
        }
        section{
            width: 100%;
            height: 100%;
        }
        .s1{
            height: 100%;
            background: repeating-linear-gradient(
              45deg,
              red,
              red 10px,
              blue 10px,
              blue 20px
            );
        }
        .s2{
            height: 150%;
            background: repeating-linear-gradient(
              45deg,
              #606dbc,
              #606dbc 10px,
              #465298 10px,
              #465298 20px
            );
        }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

</head>
<body>
    <div class="fullScreenWrapper" id="fullScreenWrapper">
        <section class="s1" ></section>
        <section class="s2"></section>
        <section class="s3" style="background: red";></section>
        <section class="s4" style="background: green";></section>
        <section class="s5" style="background: black";></section>
    </div>
    <script type="text/javascript">
        var State = class {
            constructor(heights, offset) {
                this.breakingPoints = heights;
                this.offset = offset;
                this.state = this.currentState;
            }
            get currentState(){
                return this.breakingPoints.findIndex((elm, i, arr)=> {
                    if(window.scrollY >= arr[i] && window.scrollY < arr[i+1] ){
                        return[i]
                    }
                })
            }
            get update(){
                var isUpdated = Math.sign( this.currentState - this.state)
                this.state += isUpdated;
                return isUpdated !== 0
            }
            get snapPos() {
                var offset = this.state ? this.offset : 0; // first state should not have offset.
                return this.breakingPoints[this.state] + offset;
            }
        },
        DOM = class {
            constructor(wrapper, offset) {
                this.wrapper = wrapper;
                this.offset = offset
                this.children = Array.from(wrapper.children);
                this.childHeights = [];
                this.scrollHeights = this.getScrollHeights;

                this.wrapper.classList.add('flicWrapper')
                setGlobalProperty('wrapperHeight', this.documentHeight)
                //apply custom css-values
                this.children.forEach((child, i) => {
                    child.classList.add('flicChild')

                    var height = 0 
                    if(i > 0 ){
                        var height = this.children[i-1].offsetHeight;
                    }
                    child.style.setProperty('--previousHeight', height+'px');
                    this.childHeights.push(child.offsetHeight - window.innerHeight);
                })

            }
            get getScrollHeights() {
                var heights = [0];
                //calculate al the heights
                this.children.forEach((el, i) => {
                    var mod = 2;
                    if(i === 0 || i === this.children.length -1){mod = 1}; //first and last should only have one offset
                    var elheight = el.offsetHeight - window.innerHeight + this.offset * mod;
                    heights.push( elheight + heights[i] );
                })
                return heights;
            }
            get documentHeight() {return this.scrollHeights.slice(-1)[0]+window.innerHeight-1}
        },
        Scroll = class{
            constructor(){
                this.on = true; 
            }
            throttle(fn, wait){
                var time = Date.now();
                return () => {
                    if ((time + wait - Date.now()) < 0 && this.on) {
                        fn();
                        time = Date.now();
                    }
                }
            }
        },
        scrollEvent = () => {
            if(state.update){                               //check state
                scroll.on = false;
                dom.wrapper.classList.add('transition')
                setClasses();
                setScrollPos(0,  dom.childHeights[state.state]);
                setTimeout(changeDone, 1200);
            }
        },
        setClasses = () => {
            var s = state.state;
            dom.children.forEach((child, i) => {
                let classes = child.classList;
                classes.toggle('before', i < s);
                classes.toggle('after', i > s);
                classes.toggle('active', i === s);
                classes.toggle('previous', i === s-1);
                classes.toggle('next', i === s+1);
            })
        },
        changeDone = () => {
            dom.wrapper.classList.remove('transition');
            window.scrollTo(0, state.snapPos);
            scroll.on = true;
        },
        //helper
        setGlobalProperty = (name, value) => {
            document.documentElement.style.setProperty('--'+name, (value+'px'))
        },
        setScrollPos = (pos, max) => {
            setGlobalProperty('scrollPosition', -pos)
            setGlobalProperty('stickyScrollPosition', (Math.min(pos, max)*-1))
        },

        dom = new DOM(document.getElementById('fullScreenWrapper'), 175),
        state = new State(dom.scrollHeights, dom.offset),
        scroll = new Scroll();
        setClasses();

        window.addEventListener('scroll', scroll.throttle(scrollEvent, 50));
        window.addEventListener('scroll', scroll.throttle(() => {setScrollPos(window.scrollY - state.snapPos, dom.childHeights[state.state])}, 0))
    </script>
</body>

0 个答案:

没有答案