css3實現圓形載入動畫的js外掛

專注前端30年發表於2017-07-19

這個是本人寫的一個小外掛,實現的功能也很有限,就是能夠使用圓形載入的效果。


<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>

        #circle{
            left:45%;
            top:200px;
        }

    </style>
</head>
<body>
    <div id="circle">
    </div>
</body>
<script>
    function Loading(setting) {
        this.settings ={
            animationTime:2,//動畫執行時間
            divId:null,//div盒子的idClass
            divWidth:"20px",//盒子的寬度
            divHeight:"20px", // 盒子的高度
            divLoadClassName: "spinner", //新增class名字後就會執行載入動畫
            divClass:"wrap-box",//兩個盒子外面的盒子class
            leftWrapDivName:"leftWrap-box", //第一個盒子的class名字
            leftDivName:"left-box", //第一個盒子的class名字
            rightWrapDivName:"rightWrap-box", //內部第二個盒子的class名字
            rightDivName:"right-box", //內部第二個盒子的class名字
            infinite:true, // 是否迴圈
            loadingWidth:"1px", //圓圈寬度
            loadingColor:"#30aee0" //圓圈的顏色

        };

        this.timeOut = null; //延遲器

        if(setting){
            for(var i in setting){
                this.settings[i] = setting[i];
            }
        }


        this.prefix = function () {
            var div = document.createElement('div');
            var cssText = '-webkit-transition:all .1s; -moz-transition:all .1s; -o-transition:all .1s; -ms-transition:all .1s; transition:all .1s;';
            div.style.cssText = cssText;
            var style = div.style;
            if (style.webkitTransition) {
                return '-webkit-';
            }
            if (style.MozTransition) {
                return '-moz-';
            }
            if (style.oTransition) {
                return '-o-';
            }
            if (style.msTransition) {
                return '-ms-';
            }
            return '';
        };

        this.runOne = function (callback) {
            var that = this;
            //呼叫執行一次
            this.div.classList.add(this.settings.divLoadClassName);
            this.timeOut = setTimeout(function () {
                that.div.classList.remove(that.settings.divLoadClassName);
                callback.call(that.div,that.div);
            },+that.settings.animationTime*1000);
        };

        this.runForever = function () {
            this.div.classList.add(this.settings.divLoadClassName);
        };

        this.remove = function () {
            this.leftWrap.parentNode.removeChild(this.leftWrap);
            this.rightWrap.parentNode.removeChild(this.rightWrap);
            this.style.parentNode.removeChild(this.style);
        };

        if(typeof(this.settings.divId) == "object"){
            var div = this.div = this.settings.divId;
            this.settings.divId = this.div.id;
        }else{
            var div = this.div = document.getElementById(this.settings.divId);
        }
        div.style.cssText = "border-radius:50%; width:"+this.settings.divWidth+"; height:"+this.settings.divHeight+";";
        if(!div.style.position){
            div.style.position = "absolute";
        }
        var leftWrap = this.leftWrap = document.createElement("div");
        leftWrap.className = this.settings.divClass+" "+this.settings.leftWrapDivName;
        var rightWrap = this.rightWrap = document.createElement("div");
        rightWrap.className = this.settings.divClass+" "+this.settings.rightWrapDivName;
        var left = document.createElement("div");
        left.className = this.settings.leftDivName;
        var right = document.createElement("div");
        right.className = this.settings.rightDivName;
        var style = this.style = document.createElement("style");
        leftWrap.appendChild(left);
        rightWrap.appendChild(right);
        div.appendChild(leftWrap);
        div.appendChild(rightWrap);

        style.innerText = "" +
            "@"+this.prefix()+"keyframes left-animation {" +
            "   0%{transform: rotate(135deg);}" +
            "   50%{transform: rotate(135deg);}" +
            "   100%{transform: rotate(315deg);}" +
            "}\n" +
            "@"+this.prefix()+"keyframes right-animation {" +
            "   0%{transform: rotate(-45deg);}" +
            "   50%{transform: rotate(135deg);}" +
            "   100%{transform: rotate(135deg);}" +
            "}\n" +
            "#"+this.settings.divId+" ."+this.settings.divClass+"{" +
            "   position:absolute; top:0; width:"+div.offsetWidth/2+"px; height:"+div.offsetHeight+"px; overflow:hidden;" +
            "}\n" +
            "#"+this.settings.divId+" ."+this.settings.rightWrapDivName+"{" +
            "    right:0;" +
            "}\n" +
            "#"+this.settings.divId+" ."+this.settings.leftWrapDivName+"{" +
            "   left:0;" +
            "}\n" +
            "#"+this.settings.divId+":after{" +
            "   content:''; display:block; height:4px; width:4px; position:absolute; top:50%; left:50%; margin-top:-2px; margin-left:-2px; background:"+this.settings.loadingColor+"; border-radius:50%;" +
            "}\n" +
            "#"+this.settings.divId+" ."+this.settings.leftDivName+",#"+this.settings.divId+" ."+this.settings.rightDivName+"{" +
            "   border-left:"+this.settings.loadingWidth+" solid "+this.settings.loadingColor+";" +
            "   border-top:"+this.settings.loadingWidth+" solid "+this.settings.loadingColor+";" +
            "   border-right:"+this.settings.loadingWidth+" solid transparent;" +
            "   border-bottom:"+this.settings.loadingWidth+" solid transparent;" +
            "   position:absolute;" +
            "   top:0;" +
            "   width:"+div.offsetWidth+"px;" +
            "   height:100%;" +
            "   border-radius:50%;" +
            "   box-sizing:border-box;" +
            "}\n" +
            "#"+this.settings.divId+" ."+this.settings.leftDivName+"{" +
            "   transform: rotate(135deg); left:0;" +
            "}\n"+
            "#"+this.settings.divId+" ."+this.settings.rightDivName+"{" +
            "   transform: rotate(-45deg); right:0;" +
            "}\n"+
            "#"+this.settings.divId+"."+this.settings.divLoadClassName+" ."+this.settings.leftDivName+"{" +
            "   "+this.prefix()+"animation: left-animation "+this.settings.animationTime+"s linear "+(this.settings.infinite ? "infinite":"")+
            "}\n" +
            "#"+this.settings.divId+"."+this.settings.divLoadClassName+" ."+this.settings.rightDivName+"{" +
            "   "+this.prefix()+"animation: right-animation "+this.settings.animationTime+"s linear "+(this.settings.infinite ? "infinite":"")+
            "}\n" +
            "";

        document.head.appendChild(style);
    }

    var obj = new Loading({divId:"circle"}); //例項化建構函式
    obj.runOne(function () { //只執行一次,外加傳入一個匿名函式
        console.log("動畫執行完成");
        //obj.runForever(); // 呼叫一直執行的函式
    });


</script>
</html>
以上就是全部程式碼加案例,需要在例項化的時候傳入一個物件,物件裡面需要傳入html裡面一個div盒子的id,這樣就可以自動生成相關效果。
var obj = new Loading({divId:"circle"}); //例項化建構函式
所有可以配置項為:

{
            animationTime:2,//動畫執行時間
            divId:null,//div盒子的idClass
            divWidth:"20px",//盒子的寬度
            divHeight:"20px", // 盒子的高度
            divLoadClassName: "spinner", //新增class名字後就會執行載入動畫
            divClass:"wrap-box",//兩個盒子外面的盒子class
            leftWrapDivName:"leftWrap-box", //第一個盒子的class名字
            leftDivName:"left-box", //第一個盒子的class名字
            rightWrapDivName:"rightWrap-box", //內部第二個盒子的class名字
            rightDivName:"right-box", //內部第二個盒子的class名字
            infinite:true, // 是否迴圈
            loadingWidth:"1px", //圓圈寬度
            loadingColor:"#30aee0" //圓圈的顏色

        }
例項化成功了以後,需要呼叫相關方法:

只顯示載入動畫一次:

obj.runOne();
可以傳入回撥函式。


能無限載入的動畫:

obj.runForever();


將載入功能刪除:

obj.remove();

已知bug:如果設定的載入圖形過大,會發現底部有一條白色的細縫,現在還沒有解決。由於這個效果博主是要使用到vr上面,在小尺寸上面看不出來效果,為了趕專案,先把問題保留。




相關文章