美文网首页Web前端之路让前端飞
简单实现移动端弹窗及loading组件

简单实现移动端弹窗及loading组件

作者: Chance722 | 来源:发表于2017-04-11 00:40 被阅读553次

    最近用到了很多弹窗和页面加载效果,之前只是随调随用,也没去整理,网上大多的插件要不是太冗余,就是样式风格太呆板,所以今天闲着就整理了一个出来。具备基本的弹窗功能,包括alertconrirmtips三种。(三种的区别是alert弹窗只生成确定按钮,接受确定回调。confirm弹窗生成确定和取消按钮,接受确定和取消回调。tips不生成按钮,可以设置自动隐藏或者点击遮罩层来隐藏)。组件可以更换背景文字宽高等属性,也具备选择是否添加遮罩层回调函数等基本功能。此外,也一并引入了页面loading的效果。

    组件用到了css3的动画库** animated.min.css,可以自行引入。弹窗组件主要用闭包的形式去写,支持将整个变量赋值给window,也支持用es6 module exports** 的方法供项目随处使用。下面贴上popupwin.js的代码:

    !function(){
        var popup = { //css3动画库所有动画效果 任君使用
            EFFECT:["bounce","flash","pulse","rubberBand","shake","swing","tada","wobble","bounceIn","bounceInDown","bounceInLeft","bounceInRight","bounceInUp","bounceOut","bounceOutDown","bounceOutLeft","bounceOutRight","bounceOutUp","fadeIn","fadeInDown","fadeInDownBig","fadeInLeft","fadeInLeftBig","fadeInRight",
    "fadeInRightBig","fadeInUp","fadeInUpBig","fadeOut","fadeOutDown","fadeOutDownBig","fadeOutLeft","fadeOutLeftBig","fadeOutRight","fadeOutRightBig","fadeOutUp","fadeOutUpBig","flip","flipInX","flipInY","flipOutX","flipOutY","lightSpeedIn","lightSpeedOut","rotateIn","rotateInDownLeft","rotateInDownRight",
    "rotateInUpLeft","rotateInUpRight","rotateOut","rotateOutDownLeft","rotateOutDownRight","rotateOutUpLe",
    "rotateOutUpRigt","slideInDown","slideInLeft","slideInRight","slideOutLeft","slideOutRight","slideOutUp","hinge","rollIn","rollOut"],
    
            defaultOptions:{
                themeColor: {
                    bgColor: '#e5004f', //主题背景颜色
                    fontColor: '#fff' //主题文字颜色
                },  
                type: 'alert',  //弹框类型 包括 alert、confirm、tips三种
                title: '提示',    //弹框标题
                content: '', //弹框内容
                width: '90%', //弹框宽度
                yes: '确定', //确定按钮 文本
                no: '取消', //取消按钮 文本
                isHide: false, //是否在弹出后隐藏
                onConfirm: function(){ //点击确定执行的回调函数
                    var options = {};
                    options.effect = 'bounceOut';
                    this.showAnimation('bounceOut',true);
                    this.removeMask();
                }, 
                onCancel: function(){ //点击取消执行的回调函数
                    var options = {};
                    options.effect = 'bounceOut';
                    this.showAnimation('bounceOut',true);
                    this.removeMask();
                }, 
                effect: 'bounceIn', //弹框效果
                mask: null //是否有背景遮罩层 传入透明度和是否可以点击  如{opacity: 0.8,isClick: true}
            },
            _bindEvent: function(options){
                if(options.onConfirm){
                    $(document).off('click','.confirm-btn');
                    $(document).on('click','.confirm-btn',options.onConfirm.bind(this));
                }
                if(options.onCancel){
                    $(document).off('click','.cancel-btn');
                    $(document).on('click','.cancel-btn',options.onCancel.bind(this));
                }
            },
            showAnimation: function(effect,isHide){
                //isHide参数表示弹窗在弹出后隔一段时间自动隐藏
                if(effect && this.checkEffect(effect)){
                    $('.dialog-diy').addClass(' animated '+ effect).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend',function(){
                        $(this).removeClass(' animated '+ effect);
                        if(isHide){
                            $('.dialog-diy').hide();
                        }
                    });
                }
            },
            getTemplate: function(options){
                var onConfirm = (options.onConfirm && typeof(options.onConfirm) === 'function' ?'onConfirm' : '');
                var onCancel = (options.onConfirm && typeof(options.onCancel) === 'function' ?'onCancel' : '');
                switch(options.type){
                    case 'alert': return $('<div class="popup dialog-diy" style="width:'+options.width+';left:'+getOffsetLeft(options.width)+'%">\
                                    <span class="close"></span>\
                                    <div class="pop-header" style="background:'+options.themeColor.bgColor+';color:'+options.themeColor.fontColor+'">'+options.title+'</div>\
                                    <div class="pop-body">'+options.content+'\
                                    </div>\
                                    <div class="pop-footer"><a class="confirm-btn '+onConfirm+'" >'+options.yes+'</a></div>\
                                    </div>');
                    case 'confirm': return $('<div class="popup dialog-diy" style="width:'+options.width+';left:'+getOffsetLeft(options.width)+'%">\
                                    <span class="close"></span>\
                                    <div class="pop-header" style="background:'+options.themeColor.bgColor+';color:'+options.themeColor.fontColor+'">'+options.title+'</div>\
                                    <div class="pop-body">'+options.content+'\
                                    </div>\
                                    <div class="pop-footer"><a class="cancel-btn '+onCancel+'" href="javascript:void(0)">'+options.no+'</a>\
                                    <a class="confirm-btn '+onConfirm+'" href="javascript:void(0)">'+options.yes+'</a>\
                                    </div>\
                                    </div>');
                    case 'tips': return $('<div class="popup dialog-diy" style="width:'+options.width+';left:'+getOffsetLeft(options.width)+'%">\
                                    <span class="close"></span>\
                                    <div class="pop-header" style="background:'+options.themeColor.bgColor+';color:'+options.themeColor.fontColor+'">'+options.title+'</div>\
                                    <div class="pop-body">'+options.content+'\
                                    </div>\
                                    </div>') ;
    
                }
                function getOffsetLeft(width){
                    var leftRate = 0;
                    var widthRate = Number(width.substring(0,width.length-1));
                    if(widthRate > 0 && widthRate < 100) {
                        leftRate = (100-widthRate)/2;
                    } 
                    return leftRate;
                }
            },
            removeDialog: function(){
                if($('.dialog-diy').length){
                    $('.dialog-diy').remove();
                }
                if($('#popupMask').length){
                    $('#popupMask').remove();
                }
            },
            removeMask: function(){
                if($('#popupMask').length){
                    $('#popupMask').fadeOut();
                    setTimeout(function(){
                        $('#popupMask').remove();
                    },1000);
                }
            },
            checkEffect: function(effect){
                effect = effect || "";
                if(!effect){return false;}
                var tmp = this.EFFECT.join(",");
                if(tmp.indexOf(effect)>=0){return true;}
                return false;
            },
            setMask: function(mask){
                //传入两个参数 透明度和是否可以点击 isClick为真的情況下可以通過点击遮罩层关闭弹窗
                var self = this;
                var $mask = $('<div id="popupMask" style="width:100%;height:100%;position:absolute;left:0;top:0;background:#000;opacity:'+mask.opacity+'"></div>');
                $('body').append($mask);
                if(mask.isClick){
                    $(document).off('click','#popupMask');
                    $(document).on('click','#popupMask',function(){
                        self.showAnimation('bounceOut',true);
                        self.removeMask();
                    });
                }
            },
            isDot: function(num){ //判断是否为大于0小于1的小数
                if(!isNaN(num) && num < 1){
                    return true;
                }
                return false;
            },
            alert: function(title,content,cb){ 
                var opts = this.defaultOptions;
                opts.title = title || this.defaultOptions.title;
                opts.content = content;
                opts.type = 'alert';
                if(cb && typeof cb === 'function'){
                    opts.onConfirm = cb;
                }
                var tpl = this.getTemplate(opts);
                $('body').append(tpl);
                this.showAnimation(opts.effect);
                this._bindEvent(opts);
            },
            confirm: function(title,content,cb1,cb2){
                var opts = this.defaultOptions;
                opts.title = title || this.defaultOptions.title;
                opts.content = content;
                opts.type = 'confirm';
                if(cb1 && cb1 === 'function'){
                    opts.onConfirm = cb1;
                }
                if(cb2 && cb2 === 'function'){
                    opts.onCancel = cb2;
                }
                var tpl = this.getTemplate(opts);
                $('body').append(tpl);
                this.showAnimation(opts.effect);
                this._bindEvent(opts);
            },
            tips: function(title,content){
                var self = this;
                var opts = this.defaultOptions;
                opts.title = title || this.defaultOptions.title;
                opts.content = content || '';
                opts.type = 'tips';
                var tpl = this.getTemplate(opts);
                $('body').append(tpl);
                this.showAnimation(opts.effect);
                setTimeout(function(){
                    self.showAnimation('bounceOut',true);
                    self.removeMask();
                },3000);
            },
            removeLoading: function(){
                if($('.popup-spinner').length){
                    $('.popup-spinner').fadeOut();
                    setTimeout(function(){
                        $('.popup-spinner').remove();
                    },2000);
                }
                if($('#popupMask').length){
                    $('#popupMask').fadeOut();
                    setTimeout(function(){
                        $('#popupMask').remove();
                    },2000);
                }
            },
            loading: function(opacity,isClick,color){//传入透明度,是否可以点击,加载条颜色
                if($('.popup-spinner').length){
                    $('.popup-spinner').remove();
                }
                if($('#popupMask').length){
                    $('#popupMask').remove();
                }
                var $loading = $('<div class="popup-spinner"><div style="background-color:'+color+'" class="bounce1"></div><div style="background-color:'+color+'" class="bounce2"></div><div style="background-color:'+color+'" class="bounce3"></div></div>');
                $('body').append($loading);
                var mask = {opacity:opacity,isClick:isClick};
                this.setMask(mask);
            },
            _ready: function(options){
                console.log(options);
                var self = this;
                this.removeDialog();
                var tpl = this.getTemplate(options);
                $('body').append(tpl);
                if(options.mask && this.isDot(options.mask.opacity)){
                    this.setMask(options.mask);
                }
                this.showAnimation(options.effect);
                if(options.isHide){
                    setTimeout(function(){
                        self.showAnimation('bounceOut',true);
                        self.removeMask();
                    },3000);
                    
                }
            },
            _init: function(options){
                var options = options || this.defaultOptions;
                var self = this;
                for(var key in this.defaultOptions){
                    if(options[key] == undefined){
                        options[key] = this.defaultOptions[key];
                    }
                }
                $(function(){
                    self._ready(options);
                });
                this._bindEvent(options);
            }
        };
    
        window.popup = popup; //赋值给window下的变量
        module.exports = popup; //es6模块导出
    }();
    

    可以通过 _init 函数初始化弹窗,也可以简洁调用alertconfirmtips。代码如下:

    //导入相关 js css
    import '../../common/css/popupwin.css'
    import '../../common/css/animated.css'
    import $ from 'expose-loader?!jquery'
    import popup from '../../common/js/lib/popupwin.js'
    
    //没有传递的参数将会使用组件的默认参数,参看defaultOptions
    var options = {
        themeColor: {
            bgColor: 'yellow',
            fontColor: '#000'
        }, 
        type: 'confirm',  
        title: '温馨提示',  
        content: 'hellowrod!!!', 
        width: '90%', 
        yes: '确定',
        no: '取消', 
        isHide: false, 
            onConfirm: function(){alert('just do it');},
        onCancel: null, 
        effect: 'bounceIn',
        mask: {
              opacity: 0.8,
              isClick: true
            }
    };
    
    popup._init(options); //通用方式调用
    
    //alert简洁调用
    popup.alert('提示','helloworld come from alert'); 
    
    //confirm简洁调用
    popup.confirm('提示','helloworld come from confirm',function(){
       alert('just do it'); 
    });
    
    //tips简洁调用
    popup.tips('提示','helloworld come from tips');
    
    //loading加载
    popup.loading(0.8,true,'#fff');
    
    //移除loading
    popup.removeLoading();
    
    
    

    附上popupwin.css的样式代码

    /**弹窗样式*/
    .popup{width: 90%;max-width: 500px;margin: 30px auto 0 auto;position: absolute;background: #fff;border-radius: .1rem;top: 20%;left: 5%;z-index: 999;}
    .popup .pop-header{color:#fff;padding:.08rem 0;background:#e5004f;text-align:center;font-size:.16rem;border-radius:.1rem .1rem 0 0;}
    .popup .pop-body{padding:.15rem .15rem .15rem;min-height:1rem;color:#000;font-size:.16rem;}
    .popup .pop-body.large{padding:.15rem;min-height:1rem;max-height:3rem;overflow:auto;}
    .popup .pop-footer{text-align:center;padding-bottom:.2rem}
    .popup .pop-footer .btn{width:60%;}
    
    
    /**loading动画样式**/
    .popup-spinner {width: 1rem;height: .3rem;position: absolute;top:50%;left:50%;margin-left: -.5rem;margin-top: -.15rem;line-height: .3rem;z-index: 1000;}
     
    .popup-spinner > div {width: .15rem;height: .15rem;background-color: #67CF22;margin-left: .05rem;margin-right: .05rem;border-radius: 100%;display: inline-block;-webkit-animation: bouncedelay 1.4s infinite ease-in-out;animation: bouncedelay 1.4s infinite ease-in-out;-webkit-animation-fill-mode: both;animation-fill-mode: both;}
     
    .popup-spinner .bounce1 {-webkit-animation-delay: -0.32s;animation-delay: -0.32s;}
     
    .popup-spinner .bounce2 {-webkit-animation-delay: -0.16s;animation-delay: -0.16s;}
     
    @-webkit-keyframes bouncedelay {0%, 80%, 100% { -webkit-transform: scale(0.0) }40% { -webkit-transform: scale(1.0) }}
     
    @keyframes bouncedelay {0%, 80%, 100% {transform: scale(0.0);-webkit-transform: scale(0.0);} 40% {transform: scale(1.0);-webkit-transform: scale(1.0);}}
    

    总结

    无。

    相关文章

      网友评论

        本文标题:简单实现移动端弹窗及loading组件

        本文链接:https://www.haomeiwen.com/subject/tgneattx.html