一个简单的类似scrollmagic的jq 插件的实现

function translateFun(translateArr){
    //判断鼠标滚动方向
    var str=window.navigator.userAgent.toLowerCase();//获取用户浏览器识别码,并转成小写
    var mouseDire=1;
    if(str.indexOf('firefox')!=-1){   //火狐浏览器
        document.addEventListener('DOMMouseScorll',function(e){
             //前推 -3 后拉  3
            mouseDire=e.detail>0?1:-1;
        })
    }else{
        document.onmousewheel=function(ev){  //谷歌  IE
            var e=ev||window.event;
            //前推  120  后拉-120
            mouseDire=e.wheelDelta>0?-1:1;
        }
    }

    // 初始化各需要做动画元素相关状态
    var stateObj={};
    $.each(translateArr,function(index){
        var _this=this;
        var target=$(this.target),
            translateBox=target.parents(".translate-box"),
            transformList=["scaleX","scaleY","translateX","translateY"],
            animateType={init:Object.keys(this.animate.start)},
            beChange=willChangePro(animateType.init),
            animate={init:{start:Object.assign({},this.animate.start),end:Object.assign({},this.animate.end)}},
            adapter=!!this.animate.adapter&&Object.keys(this.animate.adapter),
            adapterObj={};
        function willChangePro(type){
            var hasTrans=type.filter(function(v){ return transformList.indexOf(v) > -1 });
            return (hasTrans?"transform":"")+(type.indexOf("opacity")>0?",opacity":"");
        }
        function beAdapter(){
            stateObj[index].siteStart=translateBox.offset().top+translateBox.height()*(parseFloat(_this.site.start)/100);
            stateObj[index].siteEnd=translateBox.offset().top+translateBox.height()*(parseFloat(_this.site.end)/100);
            var isInit=true;
            
            if(!!adapter.length){  // 适配
                adapter.sort(function(a, b){return b - a});  // 设备大小从大至小排序
                $.each(adapter,function(i,k){
                    if($(window).width()<=k && (!!adapter[i+1] ? !($(window).width()< adapter[i+1]) : true)){  //小于自己并不小于自己后面那个
                        if(!stateObj[index].on[k]){  //只有到了已配置适配大小才执行函数,避免屏幕缩放反复执行
                            stateObj[index].beChange=willChangePro(animateType[k]);
                            mainScroll(stateObj[index],k);
                        }
                        isInit=false;
                    }
                })
            }
            if(!!stateObj[index].on.init){
                isInit=false;
            }
            isInit&&mainScroll(stateObj[index],"init");
        }

        $.each(adapter,function(i,k){
            adapterObj[k]={
                start:Object.assign({},animate.init.start,_this.animate.adapter[k].start),
                end:Object.assign({},animate.init.end,_this.animate.adapter[k].end)
            }
            animateType[k]=[];
            $.each(adapterObj[k].start,function(y,v){
                if(v!==adapterObj[k].end[y]){
                    animateType[k].push(y);
                }
            });
            
        });
        Object.assign(animate,adapterObj);

        stateObj[index]={
            target:target,
            translateBox:translateBox,
            isbefore:true,isafter:false,
            animateType:animateType, //
            animate:animate,  // 整理过的animate对象
            thisState:{},  // 存放当前元素当前状态
            willChange:'',
            beChange:beChange,
            on:{}
        };

      
        beAdapter();
        $(window).resize(function(){
            beAdapter();
        })

        function mainScroll(S,sizeType){
            $.each(S.on,function(k,v){
                // console.log(k);
                console.log(sizeType);
                if(k!==sizeType){
                    $(window).off("scroll",v);
                    delete S.on[k];
                }
            })

            S.on[sizeType]=function(){
                var sTop=$(window).scrollTop();
                var anim=S.animate[sizeType];
                var animtype=S.animateType[sizeType];
                if(sTop<S.siteStart){  // 该元素动画开始前
                    $.each(animtype,function(i,key){
                        S.thisState[key]=parseFloat(anim.start[key]);
                    })
                    if(!S.isbefore && !!this.beforeCb){
                        this.beforeCb();
                        S.isbefore=true;
                        S.isafter=false;
                    }
                    if(mouseDire==1){
                        if(sTop-S.siteStart<100){
                            S.willChange=S.beChange;
                        }
                    }else{
                        if(S.siteStart-sTop<100){
                            S.willChange="auto"
                        }
                    }
                }
                if(sTop>=S.siteStart&&sTop<=S.siteEnd){ // 该元素动画进行时
                    var step=(sTop-S.siteStart)/(S.siteEnd-S.siteStart);  // 当前已滚动到距离 / 总距离 (动画进行进度)
                    $.each(animtype,function(i,key){
                        S.thisState[key]=(parseFloat(anim.end[key])-parseFloat(anim.start[key]))*step + parseFloat(anim.start[key]); 
                    })
                    S.isbefore=S.isafter=false;
                }
                if(sTop>S.siteEnd){   // 该元素动画完成后
                    $.each(animtype,function(i,key){
                        S.thisState[key]=parseFloat(anim.end[key]);
                    })
                    if(!S.isafter && !!this.afterCb){
                        this.afterCb();
                        S.isbefore=false;
                        S.isafter=true;
                    }
                    if(mouseDire==1){
                        if(sTop-S.siteEnd<100){
                            S.willChange="auto"
                        }
                    }else{
                        if(S.siteEnd-sTop<100){
                            S.willChange=S.beChange;
                        }
                    }
                    
                }

                
                // console.log("matrix( "+scaleX+", 0, 0, "+scaleY+", "+transX+", "+transY+" )")
                // console.log(S.willChange);
                // console.log(S.thisState.scaleX);
                // console.log(stateObj[1].thisState.translateY?stateObj[1].thisState.translateY:0);
                S.target.css({  //  统一修改css
                            "transform":"matrix( "+((S.thisState.scaleX!=undefined)?S.thisState.scaleX:1)+", 0, 0, \
                            "+((S.thisState.scaleY!=undefined)?S.thisState.scaleY:1)+",\
                            "+(S.thisState.translateX?S.thisState.translateX:0)+", \
                            "+(S.thisState.translateY?S.thisState.translateY:0)+" )",
                            "opacity":(S.thisState.opacity!=undefined)?S.thisState.opacity:1,
                            "will-change":S.willChange?S.willChange:"auto"
                            })
            }
            $(window).on("scroll", S.on[sizeType]);
        }
    });
    
       
}
在这里插入代码片

示例:
demo.html

   <div class="translate-box">
       <div class="translate-wrap">
            <div class="cat" id="cat"></div>
            <div class="dog" id="dog"></div>
       </div>
    </div>

demo.css

body{height: 3000px;}
.translate-box{height: 300vh;}
.cat,.dog{width: 50px;height: 50px;background: rosybrown;}
.translate-wrap{position: -webkit-sticky;position: sticky;top:50px;}

demo.js

var translateArr=[
    {
        target:"#cat", // 需要执行动画的元素
        animate:{   // 执行动画
            start:{
                scaleX:1,
                translateX:"0",
                opacity:1
            },
            end:{
                scaleX:7,
                translateX:"600px",
                opacity:0
            },
            adapter:{  //适配 (可选,会继承初始配置)
                768:{
                    start:{
                        scaleX:1,
                        translateX:"0",
                        opacity:1
                    },
                    end:{
                        scaleX:7,
                        translateX:"400px",
                        opacity:1
                    },
                },
                1200:{
                    start:{
                        scaleX:1,
                        scaleY:1,
                        translateX:"0",
                        opacity:1
                    },
                    end:{
                        scaleX:10,
                        scaleY:10,
                        translateX:"200px",
                        opacity:0.8
                    },
                }
            }
        },
        site:{      // 动画开始/结束位置   相对于父translate-box 的位置百分比  (必填)
            start:50,
            end:70
        },
        beforeCb:function(){  //执行前回调 (可选)
            console.log("before");
            $(this.target).addClass('before');
        },
        afterCb:function(){    //执行完后回调 (可选)
            console.log("after")
            $(this.target).addClass("after");
        }
    },
    {
        target:"#dog",
        animate:{
            start:{
                scaleY:1,
                translateY:"0",
                translateX:"0"
            },
            end:{
                scaleY:5,
                translateY:"100px",
                translateX:"400px",
            }
        },
        site:{
            start:10,
            end:80
        }
    }
]
translateFun(translateArr);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值