首页 > 代码库 > html5 canvas头像裁剪上传

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 =http://www.mamicode.com/ 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 =http://www.mamicode.com/ canvas.toDataURL(); 81             imgValue = http://www.mamicode.com/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) + disY120                             + "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) + disX127                             + "px";128                     $("crop_handler").style.width = parseInt(_params.width) - disX129                             + "px";130                     }131                 } else if (kind === "e") {132                     if(can_move_right){133                     $("crop_handler").style.width = parseInt(_params.width) + disX134                             + "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) + disX144                             + "px";145                     $("crop_handler").style.width = parseInt(_params.width) - disX146                             + "px";147                     $("crop_handler").style.top = parseInt(_params.top) + disY148                             + "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) + disY155                             + "px";156                     $("crop_handler").style.height = parseInt(_params.height)157                             - disY + "px";158                     $("crop_handler").style.width = parseInt(_params.width) + disX159                             + "px";160                     }161                 } else if (kind === "sw") {162                     if(can_move_bottom&&can_move_left){163                     $("crop_handler").style.left = parseInt(_params.left) + disX164                             + "px";165                     $("crop_handler").style.width = parseInt(_params.width) - disX166                             + "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) + disX173                             + "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,很强大!

 

html5 canvas头像裁剪上传