• HTML5 原生API input file 来实现多图上传,并大图预览


    闲来无事,突然想用原生来实现图片的多图上传。

    一、效果图大致如下:

    1、上传时可以选择多图

    2、上传之后缩略图下过图如下:

    3、点击缩略图,大图展示当前所点击的图片,并可以左右滑动查看其它的缩略图对应的大图。效果如下:

    4、点击删除,弹出是否要删除的弹框,点击确定后,删除。效果图如下:

     

    二、要求

    1、限制图片的张数(4张)

    2、限制单个图片的大小(1M)

    3、支持拖拽上传

    4、上传后显示小图预览

    5、点击小图进行大图预览

    6、实现agax上传

    三、所需插件

    1、由于时间原因,页面布局依赖于bootstrap

    2、滚动插件用的swiper.js

    3、弹框差价layer

    四、页面布局

    4-1、缩略效果图如下:

    4-2、缩略图的HTML代码如下:

    <form action="post" class="vaildform fmreset" enctype="multipartform-data">
            <div class="form-group clearfix">
                <label class="col-lg-2  col-md-2 col-sm-2 control-label" for="userName">图册</label>
                <div class="col-lg-10 col-md-10 col-sm-10 clearfix">
                    <!-- 图片展示 -->
                    <div class="atlas-container pull-left clearfix">
                        <div class="atlas-content">
                            <i class="js-del-img fm-icon ion-close-circled"></i>
                            <div class="img-container">
                                <img src=/assets/images/logbg.png alt="图册" />
                            </div>
                        </div>
                    </div>
                    <!-- 图片上传 -->
                    <div class="upload-container pull-left">
                        <input id="fileUpload" type="file" name="" value="" multiple accept="image/png,image/gif,image/jpg,image/jpeg" />
                        <div class="fileUpload"></div>
                    </div>
                </div>
            </div>
            <div class="form-group clearfix">
                <label class="col-lg-2  col-md-2 col-sm-2 control-label" for="userName"></label>
                <div class="col-lg-10 col-md-10 col-sm-10">
                    <a id="js-submit" href="javascript:;" class="btn btn-primary">提交</a>
                </div>
            </div>
        </form>

    我们知道form表单要实现文件上传 form标签上必须有“enctype="multipartform-data"”这个属性,上传类型为post,实现文件上传的空间就是

    <input id="fileUpload" type="file" name="" value=""/>
    

     1、这是一句图片文件上传的控件,可我们想要实现图片上传,就要限制文件的类型,使用属性“accept”,accept="image/png,image/gif,image/jpg,image/jpeg",这句话用来限制图片的类型,这里列举的类型不多,大家可以根据自己的需要调整。当然你也可以写成“accept="image/*"”,不过这样写的话,点击上传,出现选择文件的框会出现很慢。

     2、有的同学会发现,这样写只能一次上传一张图片,大家别急,当我们给这个控件加上“multiple ”这个属性后就能实现多图上传啦。详细上传控件如下:

     <input id="fileUpload" type="file" name="" value="" multiple accept="image/png,image/gif,image/jpg,image/jpeg"/>

    4-3、缩略图的css布局如下:

    // 图册容器
    .atlas-container{}
    .atlas-container .atlas-content{
        margin-left:15px;
        float: left;
        position: relative;
    }
    .atlas-container .atlas-content .img-container{
        width:115px;
        height:115px;
        background:@white;
        padding:5px;
        border: 1px solid #e5e5e5;
        border-radius: 3px;
        display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
        display: -moz-box; /* 老版本语法: Firefox (buggy) */
        display: -ms-flexbox; /* 混合版本语法: IE 10 */
        display: -webkit-flex; /* 新版本语法: Chrome 21+ */
        display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
        -webkit-box-pack: center; /*子元素水平居中*/
        -moz-justify-content: center; /*子元素水平居中*/
        -webkit-justify-content: center;/*子元素水平居中*/
        justify-content: center; /*子元素水平居中*/
        -webkit-box-align: center;/*子元素交叉轴对齐方式*/
        -moz-align-items: center;/*子元素交叉轴对齐方式*/
        -webkit-align-items: center;/*子元素交叉轴对齐方式*/
        align-items: center;/*子元素交叉轴对齐方式*/
        cursor:pointer;
        position:relative;
    }
    .atlas-container .atlas-content .img-container img{
        max-width:100%;
        max-height:100%;
        display:block;
    }
    .atlas-container .atlas-content .fm-icon{
        cursor:pointer;
        font-size: 16px;
        right: -11px;
        top: -14px;
        position: absolute;
        color: rgba(0,0,0,.5);
        z-index:2;
    }
    .atlas-container .atlas-content .fm-icon:hover{color:rgba(0,0,0,.7);}
    // 上传容器
    .upload-container{
        width:120px;
        height:120px;
        margin-left:15px;
        overflow:hidden;
        position: relative;
    }
    #fileUpload{
        width:100%;
        height:100%;
        top:0;
        left:0;
        right:0;
        bottom:0;
        opacity:0;
        cursor:pointer;
        position:absolute;
        z-index:2;
    }
    .upload-container .fileUpload{
        width:100%;
        height:100%;
        cursor:pointer;
        background:@white;
        border: 1px solid #e5e5e5;
        border-radius: 3px;
        -o-border-radius: 3px;
        -moz-border-radius: 3px;
        -webkit-border-radius: 3px;
        position: relative;
    }
    .upload-container .fileUpload:before{
        content:"";
        width:32px;
        height:2px;
        background:#cbcbcb;
        top:50%;
        left:50%;
        margin-left:-16px;
        margin-top:-1px;
        position: absolute;
    }
    .upload-container .fileUpload:after{
        content:"";
        width:2px;
        height:32px;
        background:#cbcbcb;
        top:50%;
        left:50%;
        margin-left:-1px;
        margin-top:-16px;
        position: absolute;
    }

    4-4、大图HTML布局如下:

    <div class="picture-preview">
        <div class="swiper-container">
            <!-- 轮播盒子 -->
            <div class="swiper-wrapper">
            </div>
            <!-- 前进后退按钮 -->
            <div class="swiper-button-prev"></div>
            <div class="swiper-button-next"></div>
            <!-- 分页器 -->
            <div class="swiper-pagination"></div>
        </div>
    </div>

    4-5、大图对应的css样式如下:

    // 大图预览
    .picture-preview{display:none;max-height:100%;}
    .picture-preview .preview-container{
        display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
        display: -moz-box; /* 老版本语法: Firefox (buggy) */
        display: -ms-flexbox; /* 混合版本语法: IE 10 */
        display: -webkit-flex; /* 新版本语法: Chrome 21+ */
        display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
        -webkit-box-pack: center; /*子元素水平居中*/
        -moz-justify-content: center; /*子元素水平居中*/
        -webkit-justify-content: center;/*子元素水平居中*/
        justify-content: center; /*子元素水平居中*/
        -webkit-box-align: center;/*子元素交叉轴对齐方式*/
        -moz-align-items: center;/*子元素交叉轴对齐方式*/
        -webkit-align-items: center;/*子元素交叉轴对齐方式*/
        align-items: center;/*子元素交叉轴对齐方式*/
        height:100%;
    }
    .picture-preview .preview-container img{
        max-width:100%;
        max-height:100%;
        display:block;
    }

    5、js逻辑编写

    随着和html5的普及,file的各种API越来越强大,HTML5 file 的API返回了很多有用的图片信息,我们可以利用这些信息来实现图片的预览效果。

    1、我们可以在控制台上打印出我们要上传的图片信息:

     里面包含“length”->当前上传的图片个数;"lastModified"->最后的更改;“name”->图片的名字;"size"->图片的大小,"type"->图片的类型

    5-1,图片上传功能

    1、缩略图上传

    imgUpload:function(){
            var fileUpload = document.getElementById("fileUpload");         //得到图片的上传控件
            fileUpload.addEventListener('change',uploadFile,false);         // 监听上传控件
            var length=0;               // 监听图片的个数
            var size=0;                 // 监听单个图片的大小
            var url='';                 // 用来保存图片的位置
            var atlasContent = $('.atlas-container').find('.atlas-content'); 
            if(atlasContent){
                length = atlasContent.length;
                mainCtrl.picInit();           // 初始化大图容器
            }
            // 图片上传事件
            function uploadFile(){
                var files = this.files;                 // 得到files
                var lengthN =parseInt(files.length);    // 保存当前上传的个数
                length+=lengthN;                        // 图片个数
                if(length>4){                           // 图片上传超过四个
                    layer.msg('图片个数不能超过4个',function(){
                        fileUpload.value='';            // 清空当前的上传控件,
                        length=length-lengthN;          // 图片未添加,length回到原先的状态
                    });
                    return;                             // 终止程序
                }
                
                for(var i=0;i<lengthN;i++){             // 遍历当前的上传的个数,
                    size= files[i].size;                // 得到单个图片的大小
                    if(size>1024*1024){                 // 单个图片大于1M
                        layer.msg(files[i].name+'这张图片大于1M',function(){      // 提示哪张图片的大小超出1M
                            fileUpload.value='';        // 清空当前的上传控件,
                            length=length-lengthN;      // 图片未添加,length回到原先的状态
                        });
                        return;
                    }else{ 
                        var html='';                            // 缩略图
                        var bigHtml='';                         // 大图                             // 终止程序
                        url = window.URL.createObjectURL(files[i]);    // 方法会根据传入的参数创建一个指向该参数对象的URL. 这个URL的生命仅存在于它被创建的这个文档里. 新的对象URL指向执行的File对象或者是Blob对象.
                        html+='<div class="atlas-content">';
                        html+='<i class="js-del-img fm-icon ion-close-circled"></i>';
                        html+='<div class="img-container" data-name="'+files[i].name+'">';
                        html+='<img src='+url+' alt="图册"/>';
                        html+='</div>';
                        html+='</div>'; 
                        bigHtml+='<div class="swiper-slide">';
                        bigHtml+='<div class="preview-container">';
                        bigHtml+='<img src='+url+' alt="图册"/>';
                        bigHtml+='</div>';
                        bigHtml+='</div>';
                        $('.atlas-container').append(html);                     // 将缩略图片写入
                        $('.picture-preview .swiper-wrapper').append(bigHtml);  // 将大图写入
                    }
                }
                
                if(length===4){
                    $('.upload-container').hide();          // 图片上传控件隐藏
                }
    
                // 删除图片
                $('.atlas-container').on('click','.js-del-img',function(){
                    var index = $(this).index();
                    var _this = this;
                    var picName = $(this).next('.img-container').data('name');
                    layer.confirm('确定删除 '+picName+' 这张图片?', 
                        {
                            btn: ['确定','取消'] //按钮
                        }, 
                        function(){
                            $(_this).parent('.atlas-content').remove();              // 缩列图删除
                            mainCtrl.picInit();             // 重新渲染
                            length--;
                            if(length<0){length=0;}
                            $('.upload-container').show();          // 图片上传控件显示
                            layer.msg('删除成功', {icon: 1,time:1000});
                        }, 
                        function(index){
                            layer.close(index);
                        }
                    );
                })
            };
        },
    // 大图初始化
        picInit:function(){
            var thumbnailObj = $('.atlas-container').find('.atlas-content');
            var picLength = thumbnailObj.length;
            var picHtml='';
            var thumbnailImgSrc='';
            for(var i=0;i<picLength;i++){
                thumbnailImgSrc = thumbnailObj.eq(i).find('img').attr('src');
                picHtml+='<div class="swiper-slide">';
                picHtml+='<div class="preview-container">';
                picHtml+='<img src='+thumbnailImgSrc+' alt="图册"/>';
                picHtml+='</div>';
                picHtml+='</div>';
            }
            $('.picture-preview .swiper-wrapper').empty().append(picHtml);
        },

    注意:由于大图和小图不在同一个容器里,所以在缩略图改变的时候,要及时更新大图的容器

    2、点击缩略图初始化swiper插件(注意:一定要在layer的success函数里初始化,不然容易swiper比layer初始化快,swiper就不起作用了)

    picturePreview:function(){
            $('.atlas-container').on('click','.img-container',function(){
               var key = $(this).parent('.atlas-content').index(); // 保存当前小图的索引值
                layer.open({
                    type: 1,
                    shade: true,
                    shadeClose:true,
                    area: ['100%', '100%'],
                    scrollbar:false,
                    title: ['相册大图预览', 'font-size:22px;text-align:center'], 
                    content: $('.picture-preview'), //捕获的元素,注意:最好该指定的元素要存放在body最外层,否则可能被其它的相对元素所影响
                    success:function(){
                        mainCtrl.pictureCarousel(key);
                    },
                    cancel: function(index){
                        layer.close(index);
                    }
                });
            });
        },

    3、swiper滚动初始化

    pictureCarousel:function(key){
            $('.picture-preview .swiper-container .swiper-wrapper').height($(window).height()-48);  // 42是弹框标题的高度
            $(window).resize(function(){            // 监听浏览器大小的变化
                $('.picture-preview .swiper-container .swiper-wrapper').height($(window).height()-48);  // 42是弹框标题的高度
            })
            var picSwiper = new Swiper('.picture-preview .swiper-container', {
                    pagination : '.picture-preview .swiper-pagination',
                    initialSlide:key,                       // 起始页设置 
                    slidesPerView: 1,                       // 只显示1个
                    paginationClickable:true,               // 点击分页器的指示点分页器会控制Swiper切换
                    autoplay: 2000,                         // 可选选项,自动滑动
                    autoplayDisableOnInteraction:false,     // 用户操作后还可以自动切换
                    grabCursor:true,                        // 小手形状
                    paginationClickable:true,               // 分页器
                    lazyLoading:true,                       // 懒加载
                    loop:true,                              // 循环
                    // prevButton:'.picture-preview .swiper-button-prev',
                    // nextButton:'.picture-preview .swiper-button-next',
                });
            $('.picture-preview .swiper-container').hover(function(){
                picSwiper.stopAutoplay();                   // 鼠标移入禁止自动切换
            },function(){
                picSwiper.startAutoplay();                  // 鼠标移出开启自动切换
            })
            $('.picture-preview .swiper-button-prev').click(function(){         // 上一页
                picSwiper.slidePrev();
            })
            $('.picture-preview .swiper-button-next').click(function(){         // 下一页
                picSwiper.slideNext();
            })
        },

    后续:
    4-5,拖拽上传

    4-6、图片编辑剪切

    4-7、图片编辑旋转

    4-8、图片编辑大小

    4-9、显示图片上传进度

    4-10、终止、开始图片上传

  • 相关阅读:
    codeforce 266c Below the Diagonal 矩阵变换 (思维题)
    8月21日训练日记
    CodeForces 651B Beautiful Paintings
    CodeForces 651 C Watchmen
    CodeForces 17D Notepad(同余定理)
    CodeForces 19B Checkout Assistant
    Code Forces 18D Seller Bob(简单DP)
    HOJ Recoup Traveling Expenses(最长递减子序列变形)
    ZOJ 3469Food Delivery(区间DP)
    Code Forces 149DColoring Brackets(区间DP)
  • 原文地址:https://www.cnblogs.com/zuoan-oopp/p/6802932.html
Copyright © 2020-2023  润新知