Web 本地图片 canvas 截取上传

jopen 8年前

我做了一个 Web 本地图片 canvas 截取上传 的demo。发现了几个问题,记录下:

1. Canvas 元素大小 (css width height) 和表面大小(canvas 自身的 width height 属性)两个概念是不一样的,当两个大小不一致时,坐标需要进行转换计算。

// 其中 x, y 是视口坐标              function windowToCanvas(canvas, x, y) {                  var bbox = canvas.getBoundingClientRect();                  return { x: (x - bbox.left) * (canvas.width  / bbox.width),                      y: (y - bbox.top)  * (canvas.height / bbox.height)                  };              }

2.  a ndroid 老的原生 手机浏览器  Blob  构造函数有 bug (比如使用微信或qq浏览器, new Blob() 会抛出异常) 我的解决方法是使用 base64 上传,服务端解码。由于 base64 大小为原来的 4/3 倍,自然会想能不能像 c 语言那样接把字符当作 unsigned char 来看待。仔细一想 js 是不行的。因 text+=1 ,数字 1 将被转换为字符串 "1" ,而 text[i] 是仅可读,不修改!

            var clearWidth, clearHeight;              var imageLoaded = false;              var cutPoint = {x:0, y:0};              var gFileName = "";                document.getElementById('uploadbtn').onclick = function(){                  if(!imageLoaded){                      return;                  }                    var originalCanvas = document.getElementById('original');                  var canvas = document.createElement('canvas');                  var context = canvas.getContext('2d');                  canvas.width = clearWidth;                  canvas.height = clearHeight;                  context.drawImage(originalCanvas, cutPoint.x, cutPoint.y, clearWidth, clearHeight, 0, 0, clearWidth, clearHeight);                    // 注意  toDataURL 返回的默认是 png 格式                  // data 是 base64 编码                  var data = canvas.toDataURL();                  // 第二个参数的值如果在0.0和1.0之间的话, 会被看作是图片质量参数                  // 但是我测试大小没什么变化                  //var data = canvas.toDataURL('image/png', 0.5);                    var encodeData = data.split(',')[1];                  // 解 base64 编码                  var decodedData = window.atob(encodeData);                  var ia = new Uint8Array(decodedData.length);                  for (var i = 0; i < decodedData.length; i++) {                      ia[i] = decodedData.charCodeAt(i);                  };                    var blob;                  try{                      // toDataURL 返回的默认是 png 格式,所以这里固定为 image/png                      blob = new Blob([ia], {type:"image/png"});                  }catch(e){                      // 使用 http://haomou.net/2016/01/14/2016_android_blob/ 仍然无法解决                      // android 手机浏览器 Blob 构造函数 bug                      // 我的解决方法是使用 base64 上传,服务端解码    //                    alert("new Blob exception:" + e);  //                    // TypeError old chrome and FF  //                    var BlobBuilder = window.BlobBuilder ||  //                            window.WebKitBlobBuilder ||  //                            window.MozBlobBuilder ||  //                            window.MSBlobBuilder;  //  //                    alert("BlobBuilder:" + typeof(BlobBuilder));  //                    if(e.name == 'TypeError' && BlobBuilder){  //                        var bb = new BlobBuilder();  //                        bb.append([ia.buffer]);  //                        blob = bb.getBlob("image/png");  //                    } else if(e.name == "InvalidStateError"){  //                        // InvalidStateError (tested on FF13 WinXP)  //                        blob = new Blob( [ia.buffer], {type : "image/png"});  //                    }  //                    else{  //                        // We're screwed, blob constructor unsupported entirely  //                        alert("blob constructor unsupported entirely");  //                        return;  //                    }                  }                    // 修改文件名后缀格式                  var filename = gFileName;                  var index = filename.lastIndexOf('.');                  if(index >= 0){                      filename = filename.substring(0, index);                      filename += ".png";                  }                    var fd = new FormData();                  if(blob){                      fd.append('image', blob, filename);                  }else{                      // 采用 base64 上传                      fd.append("filename", filename);                      fd.append("image", encodeData);                        // 由于 base64 大小为原来的 4/3 倍,自然会想能不能像 c 语言那样                      // 直接把字符当作 unsigned char 来看待。js 是不行的。因为                      // text += 1 ,数字1将被转换为字符串"1" ,而 text[i] 是仅可读,不                      // 可修改!                  }                    // 使用 ajax 发送                  $.ajax({                      url:"http://192.168.3.102:8080/upload",                      type:"POST",                      data:fd,                      processData: false,  // 告诉jQuery不要去处理发送的数据                      contentType: false,  // 告诉jQuery不要去设置Content-Type请求头                      success:function() {                          console.log("post success.");                      },                      error: function(){                          console.log("post failed.");                      }                  });              }

来自: http://www.cnblogs.com/iexploree/p/5136877.html