jquery.form + Jcrop + CI框架实现图片裁剪上传

2013-05-08 09:53:28来源:新浪博客作者:联ian

功能:

功能:

  • 1.通过jquery.form上传图片,并按一定比例显示预览图。
  • 2.通过Jcrop裁剪图片,并显示裁剪预览图
  • 3.通过CI的图像处理类保存剪切后图片

问题:

  • 1.通过jquery.form来ajax提交file类的神奇问题
  • 2.获取ajax加载图片后图片尺寸的问题
  • 3.按比例伸缩图片
  • 4.ajax获取图片后绑定Jcrop
  • 5.CI中upload类注意事项
  • 6.图片裁剪原理

html页面代码:
 <script src="jquery-1.8.3.min.js"></script>
 <link rel="stylesheet" href="jquery.Jcrop.css">
 <script src="jquery.Jcrop.js"></script>
 <script src="jquery.form.js"></script>
 <script src="crop_photo.js"></script>
 <form id="form_photo" action="example/upload_photo" enctype="multipart/form-data" accept-charset="utf-8" method="post">
头像:<input id="photo_src" type="file" name="photo_src"/> 
</form>
<form id="save_photo" action="example/save_photo" accept-charset="utf-8" method="post">
<input type="hidden" name="p_x" id="p_x" value="">
<input type="hidden" name="p_y" id="p_y" value="">
<input type="hidden" name="p_h" id="p_h" value="">
<input type="hidden" name="p_w" id="p_w" value="">
<input type="hidden" name="p_k" id="p_k" value="">
</form>
<input id="button_photo" type="button" value="上传" />
crop_photo.js代码:
//首先是保证jquery.form能ajax提交图片
!function($){
 $(function(){
 $("#form_photo").ajaxForm();//ajaxForm()只是绑定表单事件,并不是提交表单。。。
 $("#button_photo").click(function(){
 //判断上传格式,判断图片大小好像只能在服务端检测,所以预览图片必须先传上去
 var options = {
success: showResponse,//上传成功回调函数
};
$("#form_photo").ajaxSubmit(options);//ajax上传图片,转由CI部分upload_photo
 //方法处理。另外,我上传file一直没有成功
 //过jquery.form官方文档中的submit()中再
 //回调函数ajaxForm()的方式,这种方法ajax
 //提交其它表单没问题
 });
 function showResponse(data){
//根据返回值判断上传是否成功
//成功返回图片路径
//jquery添加<img id="jcrop_photo" src="网站目录"+data />
//jquery添加<img id="preview_photo" src="网站目录"+data />
//现在开始准备
init_photo();//初始化jcrop
$("#button_photo").click(function(){ 
 $("#save_photo").submit();//再次上传剪切后图片参数到CI部分save_photo方法 });
 }
 var photo_width = 292;//设置显示预览图片的最大尺寸
 var photo_height = 292;
 function init_photo(){
 var k = 0;//记录图片伸缩比例
 var screen_img = $("#jcrop_photo");//通过new_img获取ajax加载的图片
 var new_img = new Image(); //直接获取ajax加载图片的尺寸有问题
 new_img.src = screen_img.attr("src");//反正我是这样才获得了真实的尺寸 
 setTimeout(function(){ //由于图片加载时间,可能要通过
//挂起一段时间后才能读取图片尺寸
 if((new_img.height/292) >= (new_img.width/292)){//限定长或宽最大为292
$("#jcrop_photo").css("height",292);
photo_width = Math.round(new_img.width*292/new_img.height);
$("#jcrop_photo").css("width",photo_width);
k = new_img.height/292;
 }else{
$("#jcrop_photo").css("width",292);
photo_height = Math.round(new_img.height*292/new_img.width);
$("#jcrop_photo").css("height",photo_height);
k = new_img.width/292;
 }
 $("#p_k").val(k); //将伸缩比例传给hidden表单
 $('#jcrop_photo').Jcrop({//绑定Jcrop到图片,必须在此刻绑定
onChange: show_preview,//剪切预览图 //这时候图片的DOM才被获取,不要在 
onSelect: show_preview, //ready的时候绑定,也不要jquery添
aspectRatio: 1, //加<img onload="">
 });
 },100);
 }
 function show_preview(coords){ //显示剪切后图片预览
 if (parseInt(coords.w) > 0){
var i_k = 146 / coords.w; //146为设置的预览图区域大小
$("#preview").css({
 "height": (i_k * photo_height) + 'px', //Jcrop官方文档中给出的是
 "width": (i_k * photo_width) + 'px', //指定的图片长宽,这也就是
 "marginLeft": '-' + (i_k * coords.x) + 'px', //为什么要获得真实图片尺寸
 "marginTop": '-' + (i_k * coords.y) + 'px',//的原因,具体图片原理见后文
 }).show();
 $("#p_x").val(coords.x);//将剪切位置传给hidden表单
 $("#p_y").val(coords.y);
 $("#p_h").val(coords.h);
 $("#p_w").val(coords.w);
}
 }
 });
}(window.jQuery)

php代码

upload_photo方法 //ajax上传图片
$config['upload_path'] = './img/user_head';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '4096';
$config['encrypt_name'] = true;
$this->load->library('upload', $config);//加载upload类
if(!$this->upload->do_upload('photo_src')){ //一定要写表单对应字段
echo 0; //失败返回给ajax请求0
}else{
$data = $this->upload->data();
echo $data['file_name'];//成功后返回相对路径+图片名

save_photo方法//生产裁剪后图片
$config['image_library'] = 'gd2';
$config['source_image'] = $_POST['photo_url']; 
$config['new_image'] = './img/user_head/'.'用户ID'.'.jpg';
$config['maintain_ratio'] = FALSE;//保证设置的长宽有效 
$config['x_axis'] = $_POST['p_x']*$_POST['p_k']; //一定要乘以p_k,因为这里存放的
$config['y_axis'] = $_POST['p_y']*$_POST['p_k']; //是原图而不是浏览器上经过缩放的
$config['width'] = $_POST['p_w']*$_POST['p_k'];//的图
$config['height'] = $_POST['p_h']*$_POST['p_k'];
//$this->load->library('image_lib', $config);
if ( ! $this->image_lib->crop())
{
echo $this->image_lib->display_errors();
}else{
//裁剪完毕
}

至此已经完成图片上传并裁剪保存功能,下面图解一下图片裁剪原理

jcrop裁剪后预览原理

\

注意图片的边长应该是上传图片大小除以比例K,即p.h/k。这关系到后来服务器端裁剪图片。

c.x,c.y,c.h,c.w等为jcrop提供的参数,分别是裁剪点离原图片左上角x方向距离,y方向距离,裁剪高度,宽度。

对于显示裁剪区域图片,首先要把图片缩放,缩放比例为js代码中show_preview方法的i_k,然后移动位置,将<img>放在<div syle="height:146px;width:146px;overflow:hidden">中,隐藏不必要显示的部分。

CI裁剪图片原理

\

$config['x_axis'] :据图像左上角x轴距离
$config['y_axis'] :据图像左上角y轴距离
$config['width']:裁剪的宽度
$config['height']:裁剪的长度

所以根据传来的数值,都应在相对的p_x等乘以p_k,即,比如$config['x_axis'] = $_POST['p_x']*$_POST['p_k'];

赞助商链接: