PHP Uploadify+jQuery.imgAreaSelect插件+AJAX 实现图片上传裁剪 仿微博头像上传功能

在网站中需要一个图片上传裁剪的功能,借鉴这篇文章 Ajax+PHP+jQuery图片截图上传 的指点,找到了jquery.imgAreaSelect这个不错插件,能对图片进行自定义区域选择并给出坐标,类似微博等同类网站上传头像要求按比例裁剪的功能,正合适就自己做了个。


QQ截图20130914160306


文件上传类经常使用到一个叫uploadify的插件,上面提到的文章也结合了uploadify插件的使用,只是现在版本的uploadify一些配置和方法已经改变了(3.2.1版本)。包括jquery.imgareaselect的一些API也有新的变化,在做的过程中通过查询文档才确认了一些功能和配置的用法。

下面是两个插件的地址

uploadify: http://www.uploadify.com/ ( 有 uploadifive(HTML5) 版本和 Flash 版本,顾及不支持HTML5的浏览器,目前建议选择Flash版本 )

jquery.imgareaselect: http://odyniec.net/projects/imgareaselect ( 需先有 jQuery )

具体的流程都相似,客户端uploadify替代表单接收原图,异步上传到服务器,服务器端接收后存储并返回图片文件名,取得文件名后可在浏览器显示出原图,这时在图片元素上配置imgareaselect使其可划定裁剪区域,划定结束后坐标传回服务器,PHP脚本接收换算后的坐标对原图进行裁剪。上面提到的文章中有详细的流程图,作者非常细心。

下面说说我写的过程


上细节:首先是前端的配置

demo.php:

$field = $("input[type='file']");
$field.uploadify({//配置uploadify
    'buttonText': '选择图片',  //选择按钮显示的字符
    'swf'       : '/uploadify/uploadify.swf', //swf文件的位置
    'uploader'  : '/receivePic.php', //上传的接收者
    'cancelImg' : '/uploadify/uploadify-cancel.png',
    'folder'    : '/picture',//上传图片的存放地址
    'auto'      : false,    //选择图片后是否自动上传
    'multi'     : false,   //是否允许同时选择多个(false一次只允许选中一张图片)
    'method'    : 'post',
    'queueSizeLimit' : 1,//最多能选择加入的文件数量
    'fileTypeExts': '*.gif; *.jpg; *.png', //允许的后缀
    'fileTypeDesc': 'Image Files', //允许的格式,详见文档
 
    'onSelect': function(file) {//选择文件后的触发事件
        $("a.xtPicSubmit").show().click(function(){//自定义的按钮,显示点击执行上传
            $field.uploadify('upload','*');//此处触发上传
        });
        $wrap.find("p.picInfo span").text(file.name);//file.name为选中的图片名称    
    },
 
    'onUploadSuccess' : function(file, data, response) {  //上传成功后的触发事件
        $field.uploadify('disable', true);  //(上传成功后)'disable'禁止再选择图片
        data = JSON.parse(data);  //data为接收方(receivePic.php)返回的数据,稍后描述
 
//此时开始对取回的数据处理出需要的图片名,宽高,并计算出原图比例尺,开始设定裁剪需要的计算量
 
        var orignW = data.width,//存储原图的宽高,用于计算
            orignH = data.height,
            aspectRatio = JSON.parse(picFormat)[index].width/JSON.parse(picFormat)[index].height,//提前设定的裁剪宽高比,规定随后裁剪的宽高比例
            frameW = 260,  //原图的缩略图固定宽度,作为一个画布,限定宽度,高度自适应,保证了原图比例
            frameH = 0,
            prevFrameW = 140,  //预览图容器的高宽,宽度固定,高为需要裁剪的宽高比决定
            prevFrameH = 140/aspectRatio,
            rangeX   = 1,  //初始缩放比例
            rangeY   = 1,
            prevImgW = prevFrameW,  //初始裁剪预览图宽高
            prevImgH = prevFrameW;
 
        $imgTar = $wrap.find("img.pic"),  //画布
        $imgCut = $cut.find("img.cutImg");//预览图
 
        $imgTar.attr("src","/Picture/"+data.filename);//显示已上传的图片,此时图片已在服务器上
        frameH = Math.round(frameW*orignH/orignW);//根据原图宽高比和画布固定宽计算画布高,即$imgTar加载上传图后的高。此处不能简单用.height()获取,有DOM加载的延迟
        $cut.find(".preview").css('height',Math.round(prevFrameH)+"px");//设置裁剪后的预览图的容器高,注意此时的高度应由裁剪宽高比决定,而非原图宽高比
 
//准备存放图片数据的变量,便于传回裁剪坐标
        CutJson.name = data.filename;
        CutJson.position = {};
 
//准备好数据后,开始配置imgAreaSelect使得图片可选区
        var imgArea = $imgTar.imgAreaSelect({ //配置imgAreaSelect
            instance: true,  //配置为一个实例,使得绑定的imgAreaSelect对象可通过imgArea来设置
            handles: true,   //选区样式,四边上8个方框,设为corners 4个
            fadeSpeed: 300, //选区阴影建立和消失的渐变
            aspectRatio:'1:'+(1/aspectRatio), //比例尺
 
            onSelectChange: function(img,selection){//选区改变时的触发事件
            /*selection包括x1,y1,x2,y2,width,height几个量,分别为选区的偏移和高宽。*/
                rangeX   = selection.width/frameW;  //依据选取高宽和画布高宽换算出缩放比例
                rangeY   = selection.height/frameH;
                prevImgW = prevFrameW/rangeX; //根据缩放比例和预览图容器高宽得出预览图的高宽
                prevImgH = prevFrameH/rangeY;
 
//实时调整预览图预览裁剪后效果,可参见http://odyniec.net/projects/imgareaselect/ 的Live Example
                $imgCut.css({
                    'width' : Math.round(prevImgW)+"px",
                    'height' : Math.round(prevImgH)+"px",
                    'margin-left':"-"+Math.round((prevFrameW/selection.width)*selection.x1)+"px",
                    'margin-top' :"-"+Math.round((prevFrameH/selection.height)*selection.y1)+"px"
                 
                });
            },
            onSelectEnd: function(img,selection){//放开选区后的触发事件
                //计算实际对于原图的裁剪坐标
                CutJson.position.x1 = Math.round(orignW*selection.x1/frameW);
                CutJson.position.y1 = Math.round(orignH*selection.y1/frameH);
                CutJson.position.width  = Math.round(rangeX*orignW);
                CutJson.position.height = Math.round(rangeY*orignH);
            }
        });
    }
});


此时已经取得了裁剪的坐标,只需将坐标传回服务器交给脚本处理

使用jQuery的ajax方法回传数据:

$("a.getCut").click(function(){
    $.ajax({
        type: "POST",
    url : "cutPic.php",
    data: { name:data.filename,position:JSON.stringify(CutJson.position) },
    success: function(data){
    $imgTar.attr('src',"/picture/cut/"+data); //裁剪成功传回生成的新图文件名,将结果图显示到页面
    }
   });
});

至此前端的处理就基本完成了(代码省去了一些状态显示,元素变化的处理细节),下面是后端的两个脚本:

首先是接收上传图片的脚本,接收并存储图片后返回图片数据:

receivePic.php

//上传文件处理代码与往常相同,此处省去..
 
$arr = getimagesize('/picture/'.$file['name']);
$strarr = explode("\"",$arr[3]);//分析图片宽高
$data = array(
     'filename'=>$file['name'],
     'width'=>$strarr[1],
     'height'=>$strarr[3]
 );
echo json_encode($data);

接下来是裁剪,其中也用到了PIPHP_ImageCrop裁剪函数

cutPic.php:

function PIPHP_ImageCrop($image, $x, $y, $w, $h){
   $tw = imagesx($image);
   $th = imagesy($image);
 
   if ($x > $tw || $y > $th || $w > $tw || $h > $th)
      return FALSE;
 
   $temp = imagecreatetruecolor($w, $h);
   imagecopyresampled($temp, $image, 0, 0, $x, $y,
      $w, $h, $w, $h);
   return $temp;
}
 
$pic = '/picture/'.$_POST['name'];
$cutPosition = json_decode($_POST['position']);  //取得上传的数据
$x1 = $cutPosition->x1;
$y1 = $cutPosition->y1;
$width = $cutPosition->width;
$height = $cutPosition->height;
 
$type=exif_imagetype($pic);  //判断文件类型
$support_type=array(IMAGETYPE_JPEG , IMAGETYPE_PNG , IMAGETYPE_GIF);
if(!in_array($type, $support_type,true)) {
    echo "this type of image does not support! only support jpg , gif or png";
    exit();
}
switch($type) {
            case IMAGETYPE_JPEG :
                $image = imagecreatefromjpeg($pic);
                break;
            case IMAGETYPE_PNG :
                $image = imagecreatefrompng($pic);
                break;
            case IMAGETYPE_GIF :
                $image = imagecreatefromgif($pic);
                break;
            default:
                echo "Load image error!";
                exit();
}
 
$copy = PIPHP_ImageCrop($image, $x1, $y1, $width, $height);//裁剪
 
$targetPic = '/picture/cut/'.$_POST['name'];
 
imagejpeg($copy, $targetPic);  //输出新图
 
@unlink($pic);//删除原图节省空间
 
echo $_POST['pic'].'?'.time(); //返回新图地址

整个过程就完成了。上个效果图:


QQ截图20130914160306


开始的部分很多参考了Ajax+PHP+jQuery图片截图上传 此篇详细的文章,这里再次说明。

后端的交互很轻松,任务主要在于前端两个插件之间的搭建和使用,我的代码写的比较仓促,应该需要更加结构化一点。另外上传文件的各方面控制也是一个风险(类型,大小等),值得更多的考虑。


本文也发表在我的独立博客blog.mc-zone.me上,点击访问此文


  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值