AJAX 上传图片后,使用JCrop 插件作为前端选区工具,实时预览效果,用户上传的头像图片尺寸过大时,程序会自动缩放到合理范围,防止页面被撑破。
没有使用常见的 flash 方式,可以放心在 苹果的 Mac Safari 上使用。
最终效果:
程序分析:
前端:
<script type="text/javascript" language="javascript"> var g_oJCrop = null; $(function(){ new qq.FileUploader({ element: document.getElementById('upload_avatar'),action: "controller.PHP?task=ajax_upload_avatar",multiple: false,disableDefaultDropzone: true,allowedExtensions: ["jpg","jpeg","png","gif"],uploadButtonText: '选择头像图片',onComplete: function(id,fileName,json) { if(json.success) { if(g_oJCrop!=null) g_oJCrop.destroy(); $("#crop_tmp_avatar").val(json.tmp_avatar); $("#crop_container").show(); $("#crop_target,#crop_preview").html('<img src="tmp/'+json.tmp_avatar+'">'); $('#crop_target img').Jcrop({ allowSelect: false,onChange: updatePreview,onSelect: updatePreview,aspectRatio: 1,minSize:[90,90] },function(){ g_oJCrop = this; var bounds = g_oJCrop.getBounds(); var x1,y1,x2,y2; if(bounds[0]/bounds[1] > 90/90) { y1 = 0; y2 = bounds[1]; x1 = (bounds[0] - 90 * bounds[1]/90)/2 x2 = bounds[0]-x1; } else { x1 = 0; x2 = bounds[0]; y1 = (bounds[1] - 90 * bounds[0]/90)/2 y2 = bounds[1]-y1; } g_oJCrop.setSelect([x1,y2]); }); } else { alert(json.description); } } }); }); function updatePreview(c) { $('#crop_x1').val(c.x); $('#crop_y1').val(c.y); $('#crop_x2').val(c.x2); $('#crop_y2').val(c.y2); $('#crop_w').val(c.w); $('#crop_h').val(c.h); if (parseInt(c.w) > 0) { var bounds = g_oJCrop.getBounds(); var rx = 90 / c.w; var ry = 90 / c.h; $('#crop_preview img').css({ width: Math.round(rx * bounds[0]) + 'px',height: Math.round(ry * bounds[1]) + 'px',marginLeft: '-' + Math.round(rx * c.x) + 'px',marginTop: '-' + Math.round(ry * c.y) + 'px' }); } }; function saveCropAvatar() { if($("#crop_tmp_avatar").val()=="") { alert("您还没有上传头像"); return false; } $.ajax({ type: "POST",url: "controller.PHP?task=ajax_crop",data: $("#form_crop_avatar").serialize(),dataType: "json",success: function(json) { if(json.success) { $("#crop_tmp_avatar").val(""); $("#crop_container").hide(); $("#my_avatar").html('<img src="avatars/'+json.avatar+'">'); } else { alert(json.description); } } }); } </script>
服务器端 PHP 程序佝用 GD 库进行裁切
function crop($x=0,$y=0,$width=null,$height=null) { if(!$this->image ) return false; if($x > $this->width || $y > $this->height) return false; if(!$width) $width = $this->width; if(!$height) $height = $this->height; if( ($x+$width)>$this->width ) { $width = $this->width - $x; } if( ($y+$height)>$this->height ) { $height = $this->height - $y; } $new_image = imagecreatetruecolor( $width,$height ); if( $this->type == 'image/gif' ) { $color = imagecolortransparent($this->image); imagepalettecopy($this->image,$new_image); imagefill($new_image,$color); imagecolortransparent($new_image,$color); imagetruecolortopalette($new_image,true,255); imagecopyresized($new_image,$this->image,$x,$y,$width,$height,$height); } else if( $this->type == 'image/png' || $this->type == 'image/x-png') { imagealphablending( $new_image,false ); imagesavealpha($new_image,true); $color = imagecolorallocatealpha($new_image,255,127); imagefilledrectangle( $new_image,$color); imagecopyresampled( $new_image,$height); } else { imagealphablending( $new_image,false ); imagecopyresampled( $new_image,$height); } imagedestroy($this->image); $this->image = $new_image; $this->width = $width; $this->height = $height; }
缩放
/* * 更改图像大小 $fit: 适应大小方式 'force': 把图片强制变形成 $width X $height 大小 'scale': 按比例在安全框 $width X $height 内缩放图片,输出缩放后图像大小 不完全等于 $width X $height 'scale_fill': 按比例在安全框 $width X $height 内缩放图片,安全框内没有像素的地方填充色,使用此参数时可设置背景填充色 $bg_color = array(255,255)(红,绿,蓝,透明度) 透明度(0不透明-127完全透明)) 其它: 智能模能 缩放图像并载取图像的中间部分 $width X $height 像素大小 $fit = 'force','scale','scale_fill' 时: 输出完整图像 $fit = 图像方位值 时,输出指定位置截取的部分图像 字母与图像的对应关系如下: north_west north north_east west center east south_west south south_east */ function resize_to($width = 100,$height = 100,$fit = 'center',$fill_color = array(255,127) ) { if(!$this->image ) return false; $src_x = 0; $src_y = 0; $dest_x = 0; $dest_y = 0; $src_w = $this->width; $src_h = $this->height; $dest_w = $new_width = $width; $dest_h = $new_height = $height; switch($fit) { case 'force': break; case 'scale': if($this->width*$height > $this->height*$width) { $dest_h = $new_height = intval($this->height*$width/$this->width); } else { $dest_w = $new_width = intval($this->width*$height/$this->height); } break; case 'scale_fill': if($this->width*$height > $this->height*$width) { $dest_h = intval($this->height*$width/$this->width); $dest_y = intval( ($height-$dest_h)/2 ); } else { $dest_w = intval($this->width*$height/$this->height); $dest_x = intval( ($width-$dest_w)/2 ); } break; default: if($this->width*$height > $this->height*$width) { $src_w = $width*$this->height/$height; } else { $src_h = $height*$this->width/$width; } switch($fit) { case 'north_west': $src_x = 0; $src_y = 0; break; case 'north': $src_x = intval( ($this->width-$src_w)/2 ); $src_y = 0; break; case 'north_east': $src_x = $this->width-$src_w; $src_y = 0; break; case 'west': $src_x = 0; $src_y = intval( ($this->height-$src_h)/2 ); break; case 'center': $src_x = intval( ($this->width-$src_w)/2 ); $src_y = intval( ($this->height-$src_h)/2 ); break; case 'east': $src_x = $this->width-$src_w; $src_y = intval( ($this->height-$src_h)/2 ); break; case 'south_west': $src_x = 0; $src_y = $this->height-$src_h; break; case 'south': $src_x = intval( ($this->width-$src_w)/2 ); $src_y = $this->height-$src_h; break; case 'south_east': $src_x = $this->width-$src_w; $src_y = $this->height-$src_h; break; default: $src_x = intval( ($this->width-$src_w)/2 ); $src_y = intval( ($this->height-$src_h)/2 ); } break; } $new_image = imagecreatetruecolor( $new_width,$new_height ); if( $this->type == 'image/gif' ) { imagepalettecopy($this->image,$new_image); if($fill_color[3]) { $color = imagecolorallocatealpha($new_image,$fill_color[0],$fill_color[1],$fill_color[2],$fill_color[3]); imagefill($new_image,$color); imagecolortransparent($new_image,$color); } else { $color = imagecolorallocate( $new_image,$fill_color[2] ); imagefill($new_image,$color); } imagetruecolortopalette($new_image,$dest_x,$dest_y,$src_x,$src_y,$dest_w,$dest_h,$src_w,$src_h); } else if( $this->type == 'image/png' || $this->type == 'image/x-png') { imagealphablending( $new_image,$fill_color[3]); imagefilledrectangle( $new_image,$new_width,$new_height,$src_h); } else { imagealphablending( $new_image,false ); if($fit=='scale_fill') { $color = imagecolorallocate( $new_image,$color); } imagecopyresampled( $new_image,$src_h); } imagedestroy($this->image); $this->image = $new_image; $this->width = $new_width; $this->height = $new_height; }
下载地址:http://www.1024i.com/product/6.html
示例:http://www.1024i.com/product/demo/avator_crop/v1.0/
JCrop 官方网站:http://deepliquid.com/content/Jcrop.html