浏览器图片选择预览、旋转、批量上传的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 相关文章推荐
JQuery 获得绝对,相对位置的坐标方法
Feb 09 Javascript
深入理解javascript构造函数和原型对象
Sep 23 Javascript
14个有用的Jquery技巧分享
Jan 08 Javascript
JSON与XML优缺点对比分析
Jul 17 Javascript
JavaScript中函数声明与函数表达式的区别详解
Aug 18 Javascript
关于jQuery中fade(),show()起始位置的一点小发现
Apr 25 jQuery
AngularJS自定义指令之复制指令实现方法
May 18 Javascript
基于JavaScript实现无限加载瀑布流
Jul 21 Javascript
jQueryMobile之窗体长内容的缺陷与解决方法实例分析
Sep 20 jQuery
自己动手封装一个React Native多级联动
Sep 19 Javascript
VUE项目中加载已保存的笔记实例方法
Sep 14 Javascript
vue 组件销毁并重置的实现
Jan 13 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
使用sockets:从新闻组中获取文章(二)
2006/10/09 PHP
IIS下配置Php+Mysql+zend的图文教程
2006/12/08 PHP
解析在apache里面给php写虚拟目录的详细方法
2013/06/24 PHP
Yii把CGridView文本框换成下拉框的方法
2014/12/03 PHP
php统计数组元素个数的方法
2015/07/02 PHP
求数组最大最小值方法适用于任何数组
2013/08/16 Javascript
JS实现匀速运动的代码实例
2013/11/29 Javascript
jquery教程ajax请求json数据示例
2014/01/13 Javascript
js取整数、取余数的方法
2014/05/11 Javascript
js监听鼠标点击和键盘点击事件并自动跳转页面
2014/09/24 Javascript
在JavaScript应用中实现延迟加载的方法
2015/06/25 Javascript
基于jQuery实现拖拽图标到回收站并删除功能
2015/11/25 Javascript
jQuery设置聚焦并使光标位置在文字最后的实现方法
2016/08/02 Javascript
JS动态遍历json中所有键值对的方法(不知道属性名的情况)
2016/12/28 Javascript
JS数组操作之增删改查的简单实现
2017/08/21 Javascript
Vue.js devtool插件安装后无法使用的解决办法
2017/11/27 Javascript
js实现复制功能(多种方法集合)
2018/01/06 Javascript
JavaScript中关于base64的一些事
2019/05/06 Javascript
webpack安装配置与常见使用过程详解(结合vue)
2020/06/01 Javascript
JS简易计算器实例讲解
2020/06/30 Javascript
[01:08]2014DOTA2展望TI 剑指西雅图LGD战队专访
2014/06/30 DOTA
[02:32]【DOTA2亚洲邀请赛】iceice,梦开始的地方
2017/03/13 DOTA
Python版的文曲星猜数字游戏代码
2013/09/02 Python
浅谈Python2.6和Python3.0中八进制数字表示的区别
2017/04/28 Python
Flask web开发处理POST请求实现(登录案例)
2018/07/26 Python
Linux下多个Python版本安装教程
2018/08/15 Python
python 读取Linux服务器上的文件方法
2018/12/27 Python
详解Python3序列赋值、序列解包
2019/05/14 Python
使用Python快乐学数学Github万星神器Manim简介
2019/08/07 Python
django echarts饼图数据动态加载的实例
2019/08/12 Python
使用Python刷淘宝喵币(低阶入门版)
2019/10/30 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
详解Python利用configparser对配置文件进行读写操作
2020/11/03 Python
学点简单的Django之第一个Django程序的实现
2021/02/24 Python
关于艺术节的开幕致辞
2016/03/04 职场文书
Android Studio实现简易进制转换计算器
2022/05/20 Java/Android