发现有putImageData,因此不需要手动挪动像素信息。<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Image Cutting with Canvas API</title> </head> <body> <input type="file" id="file" accept="image/*"/> <script type="text/javascript"> function createCanvas(w,h){ var canvas = document.createElement('canvas'); canvas.setAttribute('width',w); canvas.setAttribute('height',h); document.body.appendChild(canvas); return canvas; } function cutImage(img) { var h = img.height , w = img.width; //创建canvas var canvas = createCanvas(w,h); //拿到canvas的ctx var ctx = canvas.getContext('2d'); //先drawImage,然后getImageData ctx.drawImage(img,0,0,w,h); var imageData = ctx.getImageData(0,0,w,h); resolveCut(imageData, 0, 0, w/2, h/2); resolveCut(imageData, w/2, 0, w/2, h/2); resolveCut(imageData, 0, h/2, w/2, h/2); resolveCut(imageData, w/2, h/2, w/2, h/2); document.body.removeChild(canvas); } /* * @param imgData {ImageData} 要切割的图片的ImageData数据 * @param x {Number px} 左上角起始点的x坐标 * @param y {Number px} 左上角起始点的y坐标 * @param w {Number px} 要切割的矩形选区的宽度 * @param h {Number px} 要切割的矩形选区的高度 */ function resolveCut(imgData,x,y,w,h){ var cvs = createCanvas(w, h); var ctx = cvs.getContext("2d"); ctx.putImageData(imgData,-x,-y); var imgURL = cvs.toDataURL(); showImg(imgURL); document.body.removeChild(cvs); } function showImg(url) { var img = document.createElement('img'); img.src = url; img.title = "点击下载此图片"; img.onclick = function(){ download(this); }; img.setAttribute('style','border: 4px solid #FFEB00;margin: 10px;box-shadow: 0 0 10px rgba(0,0,0,.5);border-radius: 2px;cursor:pointer;'); document.body.appendChild(img); } /* * @Notice chrome最新版亲测能下载,不保证所有浏览器都能正常工作 * 其他浏览器或低版本chrome可能需要将a标签append到document中 * 或者可能需要dispatchEvent来支持 */ function download(img) { var a = document.createElement('a'); a.download = 'image_'+(new Date()).getMilliseconds()+'.png'; a.href = img.src; a.click(); } function test(src){ var imgToCut = new Image(); imgToCut.onload = function(){ cutImage(this); document.body.appendChild(document.createElement('br')); }; imgToCut.src = src; } function localFileTest() { var fileInput = document.getElementById("file"); fileInput.addEventListener('change',function(ev){ [].forEach.call(this.files,function(file){ if(file.type.match(/^image\/.+$/)) { var reader = new FileReader(); reader.onload = function(ev){ test(ev.target.result); }; reader.readAsDataURL(file); } }); }); } document.addEventListener('DOMContentLoaded',localFileTest); </script> </body> </html>
根据你这个,截图的弄好了,但是我还有个问题就是 base64 能用js 转成二进制流吗?
需要二进制流干什么呢?提交给服务器么?那这里还需要了解图片文件的二进制编码方式,DataURI到File Blob的转换,理论上是可行的,然后append到FormData中,然后提交给服务器。 function dataURItoBlob(dataURI) { // convert base64 to raw binary data held in a string // doesn't handle URLEncoded DataURIs var byteString = atob(dataURI.split(',')[1]); // separate out the mime component var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] // write the bytes of the string to an ArrayBuffer var ab = new ArrayBuffer(byteString.length); var ia = new Uint8Array(ab); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } // write the ArrayBuffer to a blob, and you're done var bb = new Blob([ab],{type:mimeString}); return bb; } var dataURL = canvas.toDataURL(); var blob = dataURItoBlob(dataURL); var fd = new FormData(document.forms[0]); fd.append("avatar", blob);
//然后就可以ajax send formData了 var xhr = new XMLHttpRequest(); xhr.open('POST','upload.php',true); xhr.send(fd); LZ做的可是上传头像?Html5完全可行的,但是目前为了兼容,一般都是上传到服务器让服务器语言切割的。
1.切完了仍然放到页面上的img内显示么?
2.切完了要传递到服务器么?
3.切完了要下载到本地么? 答:
1.如果单纯为了显示,为什么要真的把图片切成4块呢?问题转到a。
2.切完了要传递到服务器么?那,干脆把让服务器自己切吧,服务器端没有兼容性问题,服务器性能也好,反正是要传递给服务器。
3.姑且认为你要实现这个。那好吧,
3.1 曲线救国,让服务器来切,切完了再返回到客户端
3.2 我就要js切,就要,就要嘛。
那好吧,这就要动canavs的刀子了。先把image draw到canvas上,然后getImageData,就可以得到所有像素点的信息了,类似二维数组,要切成四分,就操作这些像素信息就ok了。然后再创建一个1/4大小的canvas,把这没小块的信息赋值到这个canvas中,然后toDataURI就可以拿到base64形式的小图的二进制数据了。
是canavs的刀子了 有比较全面的 html5 canavs api介绍么
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Image Cutting with Canvas API</title>
</head>
<body>
<input type="file" id="file" accept="image/*"/>
<script type="text/javascript"> function createCanvas(w,h){
var canvas = document.createElement('canvas');
canvas.setAttribute('width',w);
canvas.setAttribute('height',h);
document.body.appendChild(canvas);
return canvas;
} function cutImage(img) {
var h = img.height
, w = img.width;
//创建canvas
var canvas = createCanvas(w,h); //拿到canvas的ctx
var ctx = canvas.getContext('2d');
//先drawImage,然后getImageData
ctx.drawImage(img,0,0,w,h);
var imageData = ctx.getImageData(0,0,w,h); resolveCut(imageData, 0, 0, w/2, h/2);
resolveCut(imageData, w/2, 0, w/2, h/2);
resolveCut(imageData, 0, h/2, w/2, h/2);
resolveCut(imageData, w/2, h/2, w/2, h/2); document.body.removeChild(canvas);
} /*
* @param imgData {ImageData} 要切割的图片的ImageData数据
* @param x {Number px} 左上角起始点的x坐标
* @param y {Number px} 左上角起始点的y坐标
* @param w {Number px} 要切割的矩形选区的宽度
* @param h {Number px} 要切割的矩形选区的高度
*/
function resolveCut(imgData,x,y,w,h){
var cvs = createCanvas(w, h);
var ctx = cvs.getContext("2d"); ctx.putImageData(imgData,-x,-y);
var imgURL = cvs.toDataURL(); showImg(imgURL);
document.body.removeChild(cvs);
} function showImg(url) {
var img = document.createElement('img');
img.src = url;
img.title = "点击下载此图片";
img.onclick = function(){
download(this);
};
img.setAttribute('style','border: 4px solid #FFEB00;margin: 10px;box-shadow: 0 0 10px rgba(0,0,0,.5);border-radius: 2px;cursor:pointer;');
document.body.appendChild(img);
} /*
* @Notice chrome最新版亲测能下载,不保证所有浏览器都能正常工作
* 其他浏览器或低版本chrome可能需要将a标签append到document中
* 或者可能需要dispatchEvent来支持
*/
function download(img) {
var a = document.createElement('a');
a.download = 'image_'+(new Date()).getMilliseconds()+'.png';
a.href = img.src;
a.click();
} function test(src){
var imgToCut = new Image();
imgToCut.onload = function(){
cutImage(this);
document.body.appendChild(document.createElement('br'));
};
imgToCut.src = src;
} function localFileTest() {
var fileInput = document.getElementById("file");
fileInput.addEventListener('change',function(ev){
[].forEach.call(this.files,function(file){
if(file.type.match(/^image\/.+$/)) {
var reader = new FileReader();
reader.onload = function(ev){
test(ev.target.result);
};
reader.readAsDataURL(file);
}
});
});
} document.addEventListener('DOMContentLoaded',localFileTest); </script>
</body>
</html>
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString = atob(dataURI.split(',')[1]); // separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] // write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
} // write the ArrayBuffer to a blob, and you're done
var bb = new Blob([ab],{type:mimeString});
return bb;
} var dataURL = canvas.toDataURL();
var blob = dataURItoBlob(dataURL);
var fd = new FormData(document.forms[0]);
fd.append("avatar", blob);
//然后就可以ajax send formData了
var xhr = new XMLHttpRequest();
xhr.open('POST','upload.php',true);
xhr.send(fd);
LZ做的可是上传头像?Html5完全可行的,但是目前为了兼容,一般都是上传到服务器让服务器语言切割的。
mimeType是从dataURI里拿到的,dataURI一般格式是:
data:image/png;base64,iVBORw0KGgoA...
这里通过split就可以得到image/png。这个mimeString其实是在canvas.toDataURL的时候决定的。
canvas的toDataURL的函数原型是
toDataURL(type, jpegquality)
type和jpegquality都是可选的,如果type忽略,则默认为image/png,当type为image/jpeg时,jpegquality参数表明jpeg的质量,从0.0~1.0。不同type得到的base64串的大小不同,MIMEType也不同。