【javascript】html5中使用canvas编写头像上传截取功能
【javascript】html5中使用canvas编写头像上传截取功能
本人对canvas很是喜欢,于是想仿照新浪微博头像上传功能(前端使用canvas)
本程序目前在谷歌浏览器和火狐浏览器测试可用,ie浏览器无法支持。
因为ie的安全机制不允许img使用本地路径,所以若想ie支持本程序,必须先将图片上传,然后给img对象上传后的图片地址。
我在这里没写,是因为暂时没写上传功能的后端代码,并且还不确定有没有更好的解决办法。
一、如下是新浪的头像截取功能预览图:
二、如下是我做的截取部分
javascript代码(cavas_img_upload.js):
var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'), canvas2 = document.getElementById('canvas_dp'), context2 = canvas2.getContext('2d'), image = new Image(),//document.getElementById('myimg'), imageData, scale,//缩放比例 rubberbandRectangle = {left:10,top:20,width:180,height:150}, resize = 1; oldRubberbandRectangle = {}; dragging = false, extending = false, mousedown = {}; // Functions..................................................... function windowToCanvas(canvas, x, y) { var canvasRectangle = canvas.getBoundingClientRect(); return { x: x - canvasRectangle.left, y: y - canvasRectangle.top }; } //将截取的图片画在小的canvas中 function captureCanvasPixels() { context2.drawImage(image,rubberbandRectangle.left/scale,rubberbandRectangle.top/scale,rubberbandRectangle.width/scale,rubberbandRectangle.height/scale,0,0,180,150); } function drawRubberband() { context.save(); context.beginPath();//开始新的路径 rect(rubberbandRectangle.left, rubberbandRectangle.top, rubberbandRectangle.width, rubberbandRectangle.height); context.fillStyle='rgba(255,255,255,0.5)'; addRectanglePath(); context.fill();//填充路径 context.fillStyle='rgba(255,255,255,1)'; captureCanvasPixels();//将选取的图像copy到预览canvas中 context.beginPath(); context.strokeStyle = '#333333'; context.lineWidth = 1.0; context.arc(rubberbandRectangle.left+rubberbandRectangle.width,rubberbandRectangle.top+rubberbandRectangle.height,5,0,Math.PI*2,true); context.fill();//填充路径 context.stroke();//填充路径 context.restore(); } function rect(x, y, w, h, direction){ if(direction){//逆时针 context.moveTo(x, y); context.lineTo(x, y + h); context.lineTo(x + w, y + h); context.lineTo(x + w, y); }else{//顺时针 context.moveTo(x, y); context.lineTo(x + w, y); context.lineTo(x + w, y + h); context.lineTo(x, y + h); } context.closePath(); } function addRectanglePath(){ rect(0,0,canvas.width,canvas.height,true); } function startDragging(loc){ mousedown.x = loc.x; mousedown.y = loc.y; oldRubberbandRectangle.left = rubberbandRectangle.left; oldRubberbandRectangle.top = rubberbandRectangle.top; } function updateRubberbandRectangle(loc){ var left = oldRubberbandRectangle.left + loc.x-mousedown.x; var top = oldRubberbandRectangle.top + loc.y - mousedown.y; rubberbandRectangle.left = (left<0) ? 0 : left; rubberbandRectangle.top = (top < 0) ? 0: top; if(rubberbandRectangle.left + rubberbandRectangle.width > image.width * scale)rubberbandRectangle.left = image.width * scale - rubberbandRectangle.width; if(rubberbandRectangle.top + rubberbandRectangle.height > image.height * scale)rubberbandRectangle.top = image.height * scale - rubberbandRectangle.height; drawRubberband(); } function startExtendSelection(loc){ mousedown.x = loc.x; mousedown.y = loc.y; oldRubberbandRectangle.width = rubberbandRectangle.width; oldRubberbandRectangle.height = rubberbandRectangle.height; } function extendSelection(loc){ var width = parseInt(oldRubberbandRectangle.width) + parseInt(loc.x)-parseInt(mousedown.x); var height = parseInt(parseInt(oldRubberbandRectangle.height) * parseInt(width)/parseInt(oldRubberbandRectangle.width)); rubberbandRectangle.width = width; rubberbandRectangle.height = height; drawRubberband(); } function clearRubberbandRectangle(){ context.clearRect(0, 0, canvas.width, canvas.height); context.putImageData(imageData, 0 ,0); } // Event handlers............................................... canvas.onmousedown = function(e){ e.preventDefault(); var loc = windowToCanvas(canvas, e.clientX, e.clientY); if(rubberbandRectangle.left < loc.x && rubberbandRectangle.top < loc.y && (rubberbandRectangle.left + rubberbandRectangle.width) > loc.x && (rubberbandRectangle.top + rubberbandRectangle.height) > loc.y){ dragging = true; startDragging(loc); }else if((rubberbandRectangle.left + rubberbandRectangle.width - 3) < loc.x && (rubberbandRectangle.top + rubberbandRectangle.height - 3) < loc.y && (rubberbandRectangle.left + rubberbandRectangle.width +3) > loc.x && (rubberbandRectangle.top + rubberbandRectangle.height + 3) > loc.y){ extending = true; startExtendSelection(loc); } } canvas.onmousemove = function (e) { e.preventDefault(); var loc = windowToCanvas(canvas, e.clientX, e.clientY); if(rubberbandRectangle.left < loc.x && rubberbandRectangle.top < loc.y && (rubberbandRectangle.left + rubberbandRectangle.width) > loc.x && (rubberbandRectangle.top + rubberbandRectangle.height) > loc.y){ canvas.style.cursor='move'; }else if((rubberbandRectangle.left + rubberbandRectangle.width - 3) < loc.x && (rubberbandRectangle.top + rubberbandRectangle.height - 3) < loc.y && (rubberbandRectangle.left + rubberbandRectangle.width +3) > loc.x && (rubberbandRectangle.top + rubberbandRectangle.height + 3) > loc.y){ canvas.style.cursor='nw-resize'; }else{ canvas.style.cursor=''; } if (dragging) { clearRubberbandRectangle(); updateRubberbandRectangle(loc); } if(extending){ canvas.style.cursor='nw-resize'; clearRubberbandRectangle(); extendSelection(loc); } } canvas.onmouseup = function(e){ e.preventDefault(); dragging = false; extending = false; } // Initialization.............................................. var myfileInput = document.getElementById('myfileInput'); myfileInput.onchange=function(){ setImage(myfileInput); }; function setImage(fileObj){ if (fileObj.files && fileObj.files[0]) { //火狐下,谷歌下都是支持的 image.src = window.URL.createObjectURL(fileObj.files[0]); } else { alert('对不起,您的浏览器不支持'); } } image.src = ''; image.onload = function () { console.log(image); var w,h; //计算图片缩放比例 if(image.width>canvas.width){ console.log(1); w = canvas.width; h = canvas.width*image.height/image.width }else if(image.height>canvas.height){ console.log(2); h = canvas.height; w = canvas.height*image.width/mage.height }else if(image.width/image.height >= canvas.width/canvas.height){ console.log(3); w = canvas.width; h = canvas.width*image.height/image.width; }else if(image.width/image.height < canvas.width/canvas.height){ console.log(4); w = canvas.height*image.width/image.height h = canvas.height; } scale = w/image.width; context.clearRect(0,0,canvas.width,canvas.height); context.drawImage(image, 0, 0,w, h); console.log( w+':'+h+'###'+canvas.width+':'+canvas.height); imageData= context.getImageData(0, 0, canvas.width, canvas.height); drawRubberband(); };
html代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>CarlZhang</title> </head> <body> <div name="container" style="height:380px;width:330px;border:#92B8B1 1px solid;text-align:center"> <canvas id="canvas" style="z-index: 9999; " height="359" width="324"></canvas> </div> <!--预览--> <div name="display" style="height:150px;width:180px;border:#92B8B1 1px solid;position:absolute;left:380px;top:110px;"> <canvas id="canvas_dp" style="z-index: 9999; " height="150" width="180"></canvas> </div> <!--上传--> <input id="myfileInput" type="file" accept="image/gif, image/jpeg, image/x-png"/> <script src="js/cavas_img_upload.js" type="text/javascript" charset="utf-8"></script> </body> </html>
参考文档:
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
你要坚强,坚强的足以认识自己的弱点;你要勇敢,勇敢的足以面对自己的恐惧;你要堂堂正正。在遇到挫折时能够昂首而不背躬屈膝;你要能够面对掌声,在胜利时能够谦逊而不趾高气扬。真正的伟大直率真诚,真正的贤人虚怀若谷,真正的强者温文尔雅。——萨利·布什(林肯的继母教育林肯)