html5 canvas头像裁剪上传
效果:
在博客里有另一篇头像裁剪是用actionscript实现的头像裁剪上传,这里拥护html5,用canvas实现下。前两次的右键是为了说明不是用flash做的。
如果想要更严谨的,有技术支持的这个东西的话,可以用kissy的http://gallery.kissyui.com/imgcrop/2.0/guide/index.html.
原理很简单:裁剪框是用html做的,canvas的作用在于每次移动,变形后根据裁剪框的位置坐标以及大小,绘制图像的部分并缩放,还有绘制裁剪框区域外的灰色区域,优点也一样是不用把数据传到服务器,用服务器裁剪生成图片。
html
1 <div id="avatar_crop" class=‘inline-block‘> 2 <div id=‘wrap_crop_canvas‘ class=‘vertical_fix_parent‘> 3 <canvas id="crop_canvas" height=‘500‘ width=‘500‘></canvas> 4 </div> 5 <div id="crop_handler"> 6 <p id=‘move_proxy‘></p> 7 <div id="dragLeftTop"></div> 8 <div id="dragLeftBot"></div> 9 <div id="dragRightTop"></div> 10 <div id="dragRightBot"></div> 11 <div id="dragTopCenter"></div> 12 <div id="dragBotCenter"></div> 13 <div id="dragRightCenter"></div> 14 <div id="dragLeftCenter"></div> 15 </div> 16 </div> 17 <canvas id="crop_preview" width="105" height="100" 18 class=‘inline-block‘></canvas>
css
1 #avatar_crop,#load_img { 2 position: relative; 3 } 4 5 #avatar_crop { 6 border: 1px solid red; 7 } 8 9 #crop_preview { 10 border: 1px solid blue; 11 } 12 13 #myinfo>.inline-block { 14 vertical-align: top; 15 } 16 17 #crop_handler { 18 display: none; 19 } 20 21 #crop_handler { 22 height: 150px; 23 width: 150px; 24 position: absolute; 25 left: 0px; 26 border: 1px solid black; 27 } 28 29 #crop_control input { 30 position: absolute; 31 right: 0; 32 top: 0; 33 opacity: 0; 34 width: 100%; 35 height: 100%; 36 } 37 38 #crop_handler>div { 39 position: absolute; 40 width: 4px; 41 height: 4px; 42 border: 1px solid #000; 43 background: white; 44 overflow: hidden; 45 } 46 47 #dragLeftTop { 48 left: -3px; 49 top: -3px; 50 cursor: nw-resize; 51 } 52 53 #dragLeftBot { 54 left: -3px; 55 bottom: -3px; 56 cursor: sw-resize; 57 } 58 59 #dragRightTop { 60 right: -3px; 61 top: -3px; 62 cursor: ne-resize; 63 } 64 65 #dragRightBot { 66 right: -3px; 67 bottom: -3px; 68 cursor: se-resize; 69 } 70 71 #dragTopCenter { 72 top: -3px; 73 left: 50%; 74 margin-left: -3px; 75 cursor: n-resize; 76 } 77 78 #dragBotCenter { 79 bottom: -3px; 80 left: 50%; 81 margin-left: -3px; 82 cursor: s-resize; 83 } 84 85 #dragRightCenter { 86 right: -3px; 87 top: 50%; 88 margin-top: -3px; 89 cursor: e-resize; 90 } 91 92 #dragLeftCenter { 93 left: -3px; 94 top: 50%; 95 margin-top: -3px; 96 cursor: w-resize; 97 } 98 99 #move_proxy { 100 height: 100%; 101 cursor: move; 102 } 103 104 #wrap_crop_canvas { 105 height: 500px; 106 width: 500px; 107 border: 1px solid yellow; 108 }
js
1 require(["avalon-min"], function(avalon) { 2 var context = $("crop_canvas").getContext("2d"),img_source; 3 function getBoundary(container, target) { 4 var borderTopWidth = 0, borderRightWidth = 0, borderBottomWidth = 0, borderLeftWidth = 0, cOffset = container 5 .offset(), cOffsetTop = cOffset.top, cOffsetLeft = cOffset.left, tOffset = target 6 .offset(); 7 borderTopWidth = parseFloat(avalon.css(container,‘borderTopWidth‘)); 8 borderRightWidth = parseFloat(avalon.css(container,‘borderRightWidth‘)); 9 borderBottomWidth = parseFloat(avalon.css(container,‘borderBottomWidth‘)); 10 borderLeftWidth = parseFloat(avalon.css(container,‘borderLeftWidth‘)); 11 cOffsetTop = cOffsetTop - tOffset.top + parseFloat(avalon.css(target,‘top‘)); 12 cOffsetLeft = cOffsetLeft - tOffset.left + parseFloat(avalon.css(target,‘left‘)); 13 return { 14 top : cOffsetTop + borderTopWidth, 15 right : cOffsetLeft + container.width() - target.width()- borderRightWidth, 16 left : cOffsetLeft + borderLeftWidth, 17 bottom : cOffsetTop + container.height() - target.height() 18 - borderBottomWidth 19 }; 20 } 21 var clearSelect = ‘getSelection‘ in window ? function(){ 22 window.getSelection().removeAllRanges(); 23 } : function(){ 24 try{ 25 document.selection.empty(); 26 } 27 catch( e ){}; 28 }; 29 var file=null; 30 avalon.bind($(‘load_img‘),‘change‘,function(e){ 31 var reader = new FileReader(),files = e.target.files; 32 reader.onload = (function() { 33 return function(e) { 34 var image = new Image(); 35 image.onload = function() { 36 if(image.width>500||image.height>500){ 37 var prop=Math.min(500/image.width,500/image.height); 38 $(‘crop_canvas‘).width=image.width=image.width*prop; 39 $(‘crop_canvas‘).height=image.height=image.height*prop; 40 } 41 $(‘crop_handler‘).style.top=(500-$(‘crop_canvas‘).height)/2+‘px‘; 42 context.drawImage(image, 0, 0,image.width, image.height); 43 $(‘crop_handler‘).style.display=‘block‘; 44 img_source=image; 45 init_events(); 46 }; 47 image.src = e.target.result; 48 }; 49 })(); 50 file=files[0]; 51 reader.readAsDataURL(files[0]); 52 }); 53 function init_crop_drag(target,kind){ 54 var _params = { 55 left : 0, 56 top : 0, 57 width : 0, 58 height : 0, 59 currentX : 0, 60 currentY : 0 61 }; 62 var wrap_width=$(‘crop_canvas‘).width,wrap_height=$(‘crop_canvas‘).height; 63 avalon.bind($(target),‘mousedown‘,function(e){ 64 _params.currentX = e.clientX; 65 _params.currentY = e.clientY; 66 var p=avalon(e.target.parentNode),c=avalon($(‘avatar_crop‘)).offset(),a=$(‘crop_handler‘).style.top; 67 _params.width=p.width(); 68 _params.height=p.height(); 69 _params.top=p.offset().top-c.top; 70 _params.left= p.offset().left-c.left; 71 avalon.bind(document,‘mousemove‘,move_handler); 72 e.stopPropagation(); 73 }); 74 avalon.bind(document,‘mouseup‘,function(e){ 75 avalon.unbind(document,‘mousemove‘,move_handler); 76 screen_shot(); 77 }); 78 avalon.bind($(‘save_crop‘),‘click‘,function(){ 79 var canvas = $("crop_preview"); 80 var imgValue = canvas.toDataURL(); 81 imgValue = imgValue.substr(22); 82 avalon.ajax({ 83 url : ‘upload1.php‘, 84 type : ‘POST‘, 85 data : { 86 imgData : imgValue, 87 file_name : escape(file.name) 88 }, 89 dataType : ‘text‘, 90 success : function(data) { 91 alert("s"); 92 } 93 }); 94 }); 95 var screen_shot= function() { 96 var c =$(‘crop_preview‘); 97 var ctx = c.getContext("2d"); 98 var left = avalon($(‘crop_handler‘)).offset().left-avalon($(‘crop_canvas‘)).offset().left; 99 var top = avalon($(‘crop_handler‘)).offset().top-avalon($(‘crop_canvas‘)).offset().top; 100 var width =avalon($(‘crop_handler‘)).width(); 101 var height =avalon($(‘crop_handler‘)).height(); 102 console.log(left, top, width, height); 103 ctx.clearRect(0, 0,wrap_width,wrap_height); 104 ctx.drawImage($(‘crop_canvas‘),left,top,width,height, 0, 0, 105, 100); 105 }; 106 function move_handler(e) { 107 clearSelect(); 108 var a=avalon($(‘crop_canvas‘)).offset(); 109 var canvasTop=(500-wrap_height)/2; 110 var canvasLeft=(500-wrap_width)/2; 111 var nowX = e.clientX, nowY = e.clientY; 112 var disX = nowX - _params.currentX, disY = nowY - _params.currentY; 113 var c_h=avalon($("avatar_crop")).height(),c_w=avalon($("avatar_crop")).width(); 114 var x=parseInt(_params.left) + disX,y=parseInt(_params.top) + disY,handler_y=avalon($(‘crop_handler‘)).offset().top,handler_x=avalon($(‘crop_handler‘)).offset().left, 115 handler_width=avalon($(‘crop_handler‘)).width(),handler_height=avalon($(‘crop_handler‘)).height(); 116 var can_move_top=y>canvasTop,can_move_left=x>canvasLeft,can_move_right=x<c_w-_params.width-canvasLeft,can_move_bottom=y<c_h-_params.height-canvasTop; 117 if (kind === "n") { 118 if(can_move_top){ 119 $("crop_handler").style.top = parseInt(_params.top) + disY 120 + "px"; 121 $("crop_handler").style.height = parseInt(_params.height) 122 - disY + "px"; 123 } 124 } else if (kind === "w") { 125 if(can_move_left){ 126 $("crop_handler").style.left = parseInt(_params.left) + disX 127 + "px"; 128 $("crop_handler").style.width = parseInt(_params.width) - disX 129 + "px"; 130 } 131 } else if (kind === "e") { 132 if(can_move_right){ 133 $("crop_handler").style.width = parseInt(_params.width) + disX 134 + "px"; 135 } 136 } else if (kind === "s") { 137 if(can_move_bottom){ 138 $("crop_handler").style.height = parseInt(_params.height) 139 + disY + "px"; 140 } 141 } else if (kind === "nw") { 142 if(can_move_top&&can_move_left){ 143 $("crop_handler").style.left = parseInt(_params.left) + disX 144 + "px"; 145 $("crop_handler").style.width = parseInt(_params.width) - disX 146 + "px"; 147 $("crop_handler").style.top = parseInt(_params.top) + disY 148 + "px"; 149 $("crop_handler").style.height = parseInt(_params.height) 150 - disY + "px"; 151 } 152 } else if (kind === "ne") { 153 if(can_move_top&&can_move_right){ 154 $("crop_handler").style.top = parseInt(_params.top) + disY 155 + "px"; 156 $("crop_handler").style.height = parseInt(_params.height) 157 - disY + "px"; 158 $("crop_handler").style.width = parseInt(_params.width) + disX 159 + "px"; 160 } 161 } else if (kind === "sw") { 162 if(can_move_bottom&&can_move_left){ 163 $("crop_handler").style.left = parseInt(_params.left) + disX 164 + "px"; 165 $("crop_handler").style.width = parseInt(_params.width) - disX 166 + "px"; 167 $("crop_handler").style.height = parseInt(_params.height) 168 + disY + "px"; 169 } 170 } else if (kind === "se") { 171 if(can_move_bottom&&can_move_right){ 172 $("crop_handler").style.width = parseInt(_params.width) + disX 173 + "px"; 174 $("crop_handler").style.height = parseInt(_params.height) 175 + disY + "px"; 176 } 177 } 178 else if (kind === "drag"){ 179 if(can_move_top&&can_move_right&&can_move_bottom&&can_move_left){ 180 $("crop_handler").style.left =x+ "px"; 181 $("crop_handler").style.top = y+ "px"; 182 } 183 } 184 context.clearRect(0,0,$(‘crop_canvas‘).width,$(‘crop_canvas‘).height); 185 context.drawImage(img_source, 0, 0,img_source.width,img_source.height); 186 context.fillStyle="#1A2013"; 187 context.globalAlpha=0.5; 188 context.fillRect(0, 0, wrap_width,handler_y-a.top); 189 context.fillRect(0,handler_y-a.top,handler_x-a.left,wrap_height-handler_y+a.top); 190 context.fillRect(handler_x-a.left,handler_y-a.top+handler_height,wrap_width-handler_x+a.left,wrap_height-handler_y+a.top-handler_height); 191 context.fillRect(handler_x-a.left+handler_width,handler_y-a.top,wrap_width-handler_x+a.left-handler_width,handler_height); 192 context.globalAlpha=1; 193 e.stopPropagation(); 194 } 195 } 196 function init_events(){ 197 init_crop_drag("crop_handler","drag"); 198 init_crop_drag("dragTopCenter","n"); 199 init_crop_drag("dragLeftTop","nw"); 200 init_crop_drag("dragLeftBot","sw"); 201 init_crop_drag("dragRightTop", "ne"); 202 init_crop_drag("dragRightBot", "se"); 203 init_crop_drag("dragBotCenter", "s"); 204 init_crop_drag("dragRightCenter","e"); 205 init_crop_drag("dragLeftCenter","w"); 206 } 207 });
avalon是司徒正美https://github.com/RubyLouvre/avalon的轻量mvvc,很强大!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。