Jcrop+uploadify+php实现上传头像预览裁剪
最近由于项目需要,所以做了一个上传头像预览并且可以预览裁剪的功能,大概思路是上传的图片先保存到服务器,然后通过ajax从服务器获取到图片信息,再利用Jcrop插件进行裁剪,之后通过PHP获取到的四个裁切点的坐标进行裁剪。
首先看一下uploadify上传插件的API:
uploader : uploadify.swf 文件的相对路径,该swf文件是一个带有文字BROWSE的按钮,点击后淡出打开文件对话框,默认值:uploadify.swf。
script : 后台处理程序的相对路径 。默认值:uploadify.php
checkScript :用来判断上传选择的文件在服务器是否存在的后台处理程序的相对路径
fileDataName :设置一个名字,在服务器处理程序中根据该名字来取上传文件的数据。默认为Filedata
method : 提交方式Post 或Get 默认为Post
scriptAccess :flash脚本文件的访问模式,如果在本地测试设置为always,默认值:sameDomain
folder : 上传文件存放的目录 。
queueID : 文件队列的ID,该ID与存放文件队列的div的ID一致。
queueSizeLimit : 当允许多文件生成时,设置选择文件的个数,默认值:999 。
multi : 设置为true时可以上传多个文件。
auto : 设置为true当选择文件后就直接上传了,为false需要点击上传按钮才上传 。
fileDesc : 这个属性值必须设置fileExt属性后才有效,用来设置选择文件对话框中的提示文本,如设置fileDesc为“请选择rar doc pdf文件”,打开文件选择框效果如下图:
fileExt : 设置可以选择的文件的类型,格式如:’*.doc;*.pdf;*.rar’ 。
sizeLimit : 上传文件的大小限制 。
simUploadLimit : 允许同时上传的个数 默认值:1 。
buttonText : 浏览按钮的文本,默认值:BROWSE 。
buttonImg : 浏览按钮的图片的路径 。
hideButton : 设置为true则隐藏浏览按钮的图片 。
rollover : 值为true和false,设置为true时当鼠标移到浏览按钮上时有反转效果。
width : 设置浏览按钮的宽度 ,默认值:110。
height : 设置浏览按钮的高度 ,默认值:30。
wmode : 设置该项为transparent 可以使浏览按钮的flash背景文件透明,并且flash文件会被置为页面的最高层。 默认值:opaque 。
cancelImg :选择文件到文件队列中后的每一个文件上的关闭按钮图标,
onUploadSuccess : 上传成功后执行的函数。
$("#fileUpload").uploadify({ 'auto' : true, //选择图片后是否自动上传 'multi' : false, //是否允许同时选择多个(false一次只允许选中一张图片) 'method' : 'post', 'swf' : 'images/uploadify.swf?v=' + ( parseInt(Math.random()*1000) ), 'uploader' : 'imgReceive.php', //上传的接收者 'folder' : 'upload', //上传图片的存放地址 'fileObjName' : 'fileUpload', 'queueSizeLimit': 1, //最多能选择加入的文件数量 'height' : '120px', 'width' : '120px', 'fileSizeLimit' : '2MB', 'progressData' : 'percentage', 'fileTypeExts' : '*.jpg; *.jpeg; *.png; *.bmp; *.gif;', 'overrideEvents': ['onSelectError','onDialogClose','onQueueComplete'], 'onSelectError' : function(file) { alert('请将图片的大小限制在2MB以下!'); }, 'onUploadSuccess': function(file, data, response){ $("body").append('<div class="mask"></div>'); $("#previewWrapper").show(); var rst = JSON.parse(data); if( rst.status == 0){ var $errorTip = $("<div id='errorMsg'>上传失败:"+ rst.info +"</div>"); $("#previewBox").append($errorTip); }else{ var imageData = rst.data; var imageUrl = imageData.path //图片地址 var $image = $("<img />"); var previewBox = $("#previewBox"); previewBox.append( $image ); previewBox.children('img').attr('src', imageUrl +'?t='+ Math.random()); $("#img_url").val(imageUrl); $image.attr('id', 'previewImg'); var $previewImg = $("#previewImg"); var img = new Image(); img.src = imageUrl +'?t='+ Math.random();
//根据图片大小设置图片居中 img.onload = function() { var img_width = 0, img_height = 0, real_width = img.width, real_height = img.height; if (real_width > real_height && real_width > 400) { var ratio = real_width / 400; real_width = 400; real_height = real_height / ratio; }else if(real_height > real_width && real_height > 400) { var ratio = real_height / 400; real_height = 400; real_width = real_width /ratio; } if(real_height < 400) { img_height = (400 - real_height)/2; } if (real_width < 400) { img_width = (400- real_width)/2; } previewBox.css({ width: (400 - img_width) + 'px', height: (400 - img_height) + 'px', paddingTop: (400 - real_height)/2 }); } $("#previewImg").Jcrop({ bgFade : true, aspectRatio : 1, bgOpacity : .3, minSize : [120, 120], boxWidth : 400, boxHeight : 400, allowSelect: false, //是否可以选区, allowResize: true, //是否可以调整选区大小 onChange : showPreview, //选框改变时的事件 onSelect: showPreview, //选框选定时的事件 setSelect : [0, 0, 400, 400] }); } } });
另外取消uploadify上传的一些默认设置需要设置css:
.uploadify{width: 120px; height: 120px;}
.uploadify-button{display: none;}
.swfupload{cursor: pointer;}
.uploadify-queue{display: none;}
同时再了解一下Jcrop插件的一些基本参数说明:
参考:http://code.ciaoca.com/jquery/jcrop/
调用Jcrop:
$("#previewImg").Jcrop({ bgFade : true, aspectRatio : 1, bgOpacity : .3, minSize : [120, 120], boxWidth : 400, boxHeight : 400, allowSelect: false, //是否可以选区, allowResize: true, //是否可以调整选区大小 onChange : showPreview, //选框改变时的事件 onSelect: showPreview, //选框选定时的事件 setSelect : [0, 0, 400, 400] });
bgColor : 背景颜色。颜色关键字、HEX、RGB 均可。
bgOpacity : 背景透明度
aspectRatio : 选框宽高比。说明:width/height
boxWidth : 画布宽度
boxHeight : 画布高度 (这里两个参数一定要,不然获取的图片没办法进行CSS压缩,至少我测试是这样的)
minSelect:[0,0]:选框最小选择尺寸。说明:若选框小于该尺寸,则自动取消选择
maxSize:[0, 0] : 选框最大尺寸
minSize : [0, 0]: 选框最小尺寸
onChange : 选框改变时的事件
onSelect : 选框选定时的事件
setSelect(array):创建选框,参数格式为:[x, y, x2, y2]
------------------------------------------------------------------------------------------------------------------------------------------------------------
为了美观一点,做了一个弹出层,当点击上传的时候弹出预览框,html结构如下,
<link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" type="text/css" href="css/jquery.Jcrop.css"> <script type="text/javascript" src="js/jquery-1.11.3.min.js"></script> <script type="text/javascript" src="js/jquery.uploadify.min.js"></script> <script type="text/javascript" src="js/jquery.jcrop.js"></script> <script type="text/javascript" src="js/myupload.js"></script>
<body> <div class="main clearfix"> <div class="uploadBox"> <img src="images/default.jpg" id="avatar" alt=""> <input type="file" name="fileUpload" id="fileUpload" title="支持jpg、jpeg、gif、png格式,文件小于10M"> </div> </div> <div class="previewWrapper" id="previewWrapper"> <div id="previewBox"></div> <form action="crop.php" method="post"> <input type="hidden" id="x" name="x" /> <input type="hidden" id="y" name="y" /> <input type="hidden" id="w" name="w" /> <input type="hidden" id="h" name="h" /> <input type="hidden" id="img_url" name="src"> <p class="crop-tip">温馨提示:请选择要裁剪的区域</p> <div class="previewBtn"> <a href="javascript:;" id="cancel">取消</a> <a href="javascript:;" id="confirm">确定</a> </div> </form> </div> </body>
裁剪的JS代码:
//提交裁剪好的图片 var CutJson = {}; function showPreview(coords) { var img_width = $("#previewImg").width(); var img_height = $("#previewImg").height(); var img_url = $("#img_url").val(); CutJson = { 'path': img_url, 'x': Math.floor(coords.x), 'y': Math.floor(coords.y), 'w': Math.floor(coords.w), 'h': Math.floor(coords.h) }; console.log(CutJson); } //取消操作 $("#cancel").click(function() { $("#previewBox").find('*').remove(); $("#previewWrapper").hide(); $(".mask").remove(); }); //确认裁剪
$("#confirm").click(function() {
$.ajax({
url: 'crop.php',
type: 'POST',
dataType: 'json',
data: {'crop': CutJson},
success: function(data, status, xhr) {
// console.log(data);
$("#avatar").attr("src",data.url);
$("#previewBox").find('*').remove();
$("#previewWrapper").hide();
$(".mask").remove();
}
});
})
接收上传图片的imgReceive.php文件和裁剪的crop.php文件如下:
imgReceive.php
<?php header("Content-type: text/html; charset=utf-8"); $Handle = new UploadReceive(); $data = $Handle->receive($_FILES['fileUpload'],'/upload/'); echo json_encode($data); class UploadReceive { public function receive($file, $path) { //存储相对地址 $path = trim($path, '/').'/'; $savepath = rtrim(dirname(__FILE__),'/').'/'.$path; //初始检测 if($file['error'] > 0) { $data['status'] = 0; switch ($file['error']) { case 1: $data['info'] = '文件大小超过服务器限制'; break; case 2: $data['info'] = '文件太大!'; break; case 3: $data['info'] = '文件只加载了一部分!'; break; case 4: $data['info'] = '文件加载失败!'; break; } return $data; } //大小检测 if($file['size'] > 2*1024*1024){ $data['status'] = 0; $data['info'] = '文件过大!'; return $data; } //类型检测 $ext = pathinfo($file['name'], PATHINFO_EXTENSION); $typeAllow = array('jpg','jpeg','gif','png'); if( in_array($ext, $typeAllow) ) { $imginfo = getimagesize($file['tmp_name']); if (empty($imginfo) || ($ext == 'gif' && empty($imginfo['bits']))) { $data['status'] = 0; $data['info'] = '非法图像文件'; return $data; } }else{ $data['status'] = 0; $data['info'] = '文件类型不符合!只接收'.implode(',',$typeAllow).'类型图片'; return $data; } //存储 $time = uniqid('upload_'); if (!is_dir($savepath)) { if (!mkdir($savepath, 0777, true)) { $data['status'] = 0; $data['info'] = '上传目录不存在或不可写!请尝试手动创建:'.$savepath; return $data; } }else { if (!is_writable($savepath)) { $data['status'] = 0; $data['info'] = '上传目录不可写!:'.$savepath; return $data; } } $filename = $time .'.'. $ext; $upfile = $savepath . $filename; if(is_uploaded_file($file['tmp_name'])){ if(!move_uploaded_file($file['tmp_name'], $upfile)){ $data['status'] = 0; $data['info'] = '移动文件失败!'; return $data; }else{ $data['status'] = 1; $data['info'] = '成功'; $arr = getimagesize( $upfile ); $strarr = explode("\"",$arr[3]);//分析图片宽高 $data['data'] = array( 'path'=>$path.$filename, 'name'=>$filename, 'width'=>$strarr[1], 'height'=>$strarr[3] ); return $data; } }else{ $data['status'] = 0; $data['info'] = '文件丢失或不存在'; return $data; } } } ?>
crop.php
<?php header("Content-type: text/html; charset=utf-8"); $crop = $_POST['crop']; if($crop) { $targ_w = $targ_h = 120; $src = $crop['path']; $pathinfo = pathinfo($src); $filename = 'upload/small_'.$pathinfo['basename']; $img_r = imagecreatefromjpeg($src); //从url新建一图像 $dst_r = imagecreatetruecolor($targ_w, $targ_h); //创建一个真色彩的图片源 imagecopyresampled($dst_r, $img_r, 0, 0, $crop['x'], $crop['y'], $targ_w, $targ_h, $crop['w'], $crop['h']); imagejpeg($dst_r, $filename, 90);
$data["url"]=$filename;
echo json_encode($data);
exit;
} /** * 裁剪不同图像的类 */ class cutImages { private $filename; //原文件全路径 private $x; //横坐标 private $y; //纵坐标 private $x1; //源图宽 private $y1; //源图高 private $ext; //文件后缀 private $width=120; //宽 private $height=120; //高 private $jpeg_quality=90; //图片生成的保真度 范围0(质量最差)-100(质量最好) function __construct() { } public function initialize($filename, $x, $y, $x1, $y1) { if(file_exists($filename)) { $this->filename = $filename; $pathinfo = pathinfo($filename); $this->ext = strtolower($pathinfo['extension']); //将扩展名转换为小写 }else { $err = new Exception ('文件不存在!', 1050); throw $err; } $this->x = $x; $this->y = $y; $this->x1 = $x1; $this->y1 = $y1; } /** * 生成截图 * 根据不同的图片格式生成不同的截图 */ public function generateShot() { switch ($this->ext) { case 'jpg': $this-> generateJpg(); break; case 'png': $this-> generatePng(); break; case 'gif': $this-> generateGif(); break; default: return false; } } /** * 获取生成的小图文件 * */ public function getShotName() { $pathinfo = pathinfo($this->filename); $fileinfo = explode('.', $pathinfo['basename']); $cutfilename = $fileinfo[0].'_small'.$this->ext; return $pathinfo['dirname'].'/'.$cutfilename; } /** *生成jpg格式图片 */ public function generateJpg() { $shotname = $this->getShotName(); $img_r = imagecreatefromjpeg($this->filename); $dst_r = imagecreatetruecolor($this->width, $this->height); imagecopyresampled($dst_r, $img_r, 0, 0, $this->x, $this->y, $this->width, $this->height, $this->x1, $this->y1); imagejpeg($dst_r, $shotname, $this->jpeg_quality); return $shotname; } /** *生成png格式图片 */ public function generatePng() { $shotname = $this->getShotName(); $img_r = imagecreatefrompng($this->filename); $dst_r = imagecreatetruecolor($this->width, $this->height); imagecopyresampled($dst_r, $img_r, 0, 0, $this->x, $this->y, $this->width, $this->height, $this->x1, $this->y1); imagepng($dst_r, $shotname, $this->jpeg_quality); return $shotname; } /** *生成gif格式图片 */ public function generateGif() { $shotname = $this->getShotName(); $img_r = imagecreatefromgif($this->filename); $dst_r = imagecreatetruecolor($this->width, $this->height); imagecopyresampled($dst_r, $img_r, 0, 0, $this->x, $this->y, $this->width, $this->height, $this->x1, $this->y1); imagegif($dst_r, $shotname, $this->jpeg_quality); return $shotname; } } ?>
最终效果如图:
转载:
http://www.cnblogs.com/yuanbiao/p/5007287.html