浏览器图片选择预览、旋转、批量上传的JS代码实现


Posted in Javascript onDecember 04, 2013

工作中遇到的业务场景,和同事一起研究了下,主要是为了兼容IE版本

其实就是一些琐碎的知识点在网上搜集下解决方式,然后集成了下,主要有以下点:

1. IE input type=file的图片预览要用IE的filter css

    progid:DXImageTransform.Microsoft.AlphaImageLoader

   chrome/firefox则用File api的file reader

2. 图片旋转,IE用progid:DXImageTransform.Microsoft.Matrix的filter(filter可以组合用,用空格隔开)

   chrome/firefox用canvas

3. 上传图片,我用的都是不可见的iframe 里的form动态的添加input[type=file]去实现。chrome/firefox可以用xhr,但我懒得去修改了

4. 其中为了实现上传图片不刷新本页面,又能反复选择文件,所以还用一个iframe专门维护一个input[type=file]的列表,比较偷巧。

浏览器图片选择预览、旋转、批量上传的JS代码实现

可以参考下代码,主要是一个主html,然后两个iframe的html,上传的服务端返回的数据为上传成功的file name,用于删除预览图。

// 上传回调
        // resultList -> ['file1', 'file2'] 为上传成功的file name
        var uploadCallback = function(resultList){
            console.log(JSON.stringify(resultList));
            var i = 0;
            for(; i < resultList.length; i++){
                var index = resultList[i].substr('file'.length);
                $(':checkbox[value=' + index + ']').parent().parent().remove();
            }
        };
        $(function(){
            // 保存图片旋转的角度,以便提交给服务端处理
            var rotateAng = {};
            // 用于命名后缀的序号
            var cc = 0;
            // 如果是chrome/ff,需要用file api去生成img
            var genImgTpl = function(input, index){
                return '<img src="/webx/public/1.png" class="main" id="img' + index + '" />';
            };
            var readImgFromInput = function(_input, index){
                var inputDom = _input[0];
                // chrome/ff
                if(inputDom['files']){
                    var reader = new FileReader();
                    reader.onload = function(e){
                        $('img.main:last').attr({src : e.target.result});
                    }
                    reader.readAsDataURL(inputDom['files'][0]);
                }else{
                    var src = _input[0].value;
                    var imgDom = $('#img' + index);
                    imgDom.attr('src-old', src);
                    imgDom.css({
                        float: 'left',
                        position: 'relative',
                        overflow: 'hidden',
                        width: '195px',
                        height: '195px'
                    });
                    imgDom.css({'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',sizingMethod='scale',src=\"" + src + "\")"});
                }
            };
            var showImg = function(_input){
                var index = ++cc;
                _input.addClass('hide');
                _input.attr('name', 'file' + index);
                _input.attr('data-index', index);
                var iframeWin = $('#choose')[0].contentWindow;
                iframeWin.addInput(_input);
                var tpl = '<div>' + genImgTpl(_input, index) + 
                    '<span class="choose"><input type="checkbox" value="' + index + '" checked="true" /></span>' + 
                    '<span class="opts turn-right"><img src="img/rightBtn.png" /></span>' + 
                    '</div>';
                $('#imgDiv').append(tpl);
                readImgFromInput(_input, index);
            };
            var addAnother = function(){
                $('#uploadBtn').before('<input type="file" name="file" />');
            };
            // input[type=file]的绑定事件
            $('#uploadDiv input').live('change', function(){
                var path = this.value;
                if(!path){
                    return;
                }
                showImg($(this));
                addAnother();
            });
            // 可以在checkbox时候remove input
//            $('#imgDiv input:checkbox').live('change', function(){
//                var isChecked = $(this).is(':checked');
//                console.log(isChecked);
//            });
            $('#imgDiv span.turn-right').live('click', function(){
                // 上次旋转的角度
                var index = $(this).siblings('span.choose').find('input').val();
                var oldAng = rotateAng[index] || 0;
                var newAng = oldAng + 90;
                rotateAng[index] = newAng;
                $('#img' + index).rotate(90);
            });
            // 表单提交时候根据checkbox,删除未choose的input[type=file]
            $('#uploadBtn').click(function(){
                var choosedNum = $('#imgDiv input:checkbox').filter(':checked').length;
                if(!choosedNum){
                    alert('请选择上传文件!');
                    return false;
                }
                // 选中的序号数组
                var choosedIndexList = $('#imgDiv input:checkbox').filter(':checked').map(function(){
                    return this.value;
                }).get();
                // 两个iframe,一个用于保存选择的input[type=file]
                // 一个用于form upload
                var uploadIframe = $('#upload')[0].contentWindow;
                var chooseIframe = $('#choose')[0].contentWindow;
                var i = 0;
                for(; i < choosedIndexList.length; i++){
                    var index = choosedIndexList[i];
                    var inputFile = chooseIframe.$('#uploadDiv input').filter('[data-index=' + index + ']');
                    uploadIframe.$('#uploadForm').append(inputFile);
                    // 旋转度数
                    var ang = rotateAng[index] || 0;
                    if(ang % 360 != 0){
                        var tplInput = '<input type="hide" name="ang' + index + '" value="' + ang + '" />';
                        uploadIframe.$('#uploadForm').append(tplInput);
                    }
                }
                uploadIframe.doUpload();
                return false;
            });
        });

IE7、8、9和chrome中测试没有问题
Javascript 相关文章推荐
自动检查并替换文本框内的字符
Jun 30 Javascript
java script编程起步(第三课)
Jan 10 Javascript
js和jquery使按钮失效为不可用状态的方法
Jan 26 Javascript
实现前后端数据交互方法汇总
Apr 07 Javascript
使用AngularJS实现可伸缩的页面切换的方法
Jun 19 Javascript
JavaScript中利用jQuery绑定事件的几种方式小结
Mar 06 Javascript
js简单实现调整网页字体大小的方法
Jul 23 Javascript
js实现数组和对象的深浅拷贝
Sep 30 Javascript
手把手教你vue-cli单页到多页应用的方法
May 31 Javascript
vue-cli3使用 DllPlugin 实现预编译提升构建速度
Apr 24 Javascript
vue自定义js图片碎片轮播图切换效果的实现代码
Apr 28 Javascript
浅谈vue.watch的触发条件是什么
Nov 07 Javascript
jquery内置验证(validate)使用方法示例(表单验证)
Dec 04 #Javascript
两个数组去重的JS代码
Dec 04 #Javascript
jquery使用jquery.zclip插件复制对象的实例教程
Dec 04 #Javascript
验证控件与Button的OnClientClick事件详细解析
Dec 04 #Javascript
快速解决FusionCharts联动的中文乱码问题
Dec 04 #Javascript
js跑步算法的实现代码
Dec 04 #Javascript
如何在JavaScript中实现私有属性的写类方式(二)
Dec 04 #Javascript
You might like
广播爱好者需要了解的天线知识
2021/03/01 无线电
PHP中的函数-- foreach()的用法详解
2013/06/24 PHP
PHP互换两个变量值的方法(不用第三变量)
2016/11/14 PHP
php 中htmlentities导致中文无法查询问题
2018/09/10 PHP
arguments对象
2006/11/20 Javascript
基于jQuery的为attr添加id title等效果的实现代码
2011/04/20 Javascript
9款2014最热门jQuery实用特效推荐
2014/12/07 Javascript
jQuery实现多级联动下拉列表查询框
2016/01/18 Javascript
JS控制层作圆周运动的方法
2016/06/20 Javascript
微信小程序 Record API详解及实例代码
2016/09/30 Javascript
浅谈AngularJs指令之scope属性详解
2016/10/24 Javascript
微信小程序 出现47001 data format error原因解决办法
2017/03/10 Javascript
vue之数据交互实例代码
2017/06/20 Javascript
webpack源码之loader机制详解
2018/04/06 Javascript
jQuery表单选择器用法详解
2019/08/22 jQuery
JS回调函数简单易懂的入门实例分析
2019/09/29 Javascript
vue 解决异步数据更新问题
2019/10/29 Javascript
微信浏览器下拉黑边解决方案 wScroollFix
2020/01/21 Javascript
[34:08]2018DOTA2亚洲邀请赛3月29日 小组赛B组 VP VS EG
2018/03/30 DOTA
解决Python requests 报错方法集锦
2017/03/19 Python
Python实现基于多线程、多用户的FTP服务器与客户端功能完整实例
2017/08/18 Python
Python实现感知器模型、两层神经网络
2017/12/19 Python
Python使用selenium实现网页用户名 密码 验证码自动登录功能
2018/05/16 Python
python xpath获取页面注释的方法
2019/01/14 Python
使用TFRecord存取多个数据案例
2020/02/17 Python
HTML5之SVG 2D入门10—滤镜的定义及使用
2013/01/30 HTML / CSS
adidas澳大利亚官方网站:adidas Australia
2018/04/15 全球购物
优秀大学生的自我评价
2014/01/16 职场文书
成人继续教育实施方案
2014/03/01 职场文书
土木工程师职业规划范文
2014/03/07 职场文书
函授生自我鉴定
2014/03/25 职场文书
市场营销毕业生自荐信范文
2014/04/01 职场文书
师范大学生求职信
2014/06/13 职场文书
自主招生学校推荐信
2014/09/26 职场文书
特别篇动画《总之就是非常可爱 ~制服~》PV公开,2022年夏季播出
2022/04/04 日漫
JavaScript中的LHS和RHS分析详情
2022/04/06 Javascript