前端JS裁剪图片与后端PHP保存的完整实现

作者:百宝袋时间:2026-10-21 23:28:59浏览:112

本文介绍利用JavaScript插件Jcrop实现前端图片裁剪,并通过获取裁剪坐标传递给后端PHP处理。前端负责显示裁剪框与预览,后端使用ThinkPHP框架调用GD库imagecopy函数完成图片保存,解决了前端不直接操作图片数据的问题。

前言与实现目标

前言

在网页设计中,诸如滑动验证码和图片裁剪等交互效果往往能提升页面的灵动性。

早期工作中我一直希望了解这些技术,但缺乏实际应用场景。近日利用空闲时间深入研究,期间虽遇到诸多问题,但也暴露出自身基础知识的不足。

基础知识相对薄弱。

实现效果:

用户点击上传图片后,页面将展示原图,并出现裁剪框及两个预览区域。最终点击裁剪按钮,即可将裁剪后的图片保存至服务器。

该功能看似简单,但实现过程中主要面临两个难点:一是前端裁剪交互效果的实现,二是图片数据的后端处理。

针对前端问题,我引用了一款网络插件。体验下来,该插件仅支持正方形区域裁剪,尽管边框有八个控制点,但拖动时仍按正方形缩放,这点体验略显不足。

具体实现方法如下:

前端页面与JS实现

以下是基础的页面结构设计:


<div style="float:left;"><img id="target"></div>
<div style="width:48px;height:48px;margin:10px;overflow:hidden; float:left;"><img style="float:left;" id="preview" ></div>
<div style="width:190px;height:195px;margin:10px;overflow:hidden; float:left;"><img style="float:left;" id="preview2" ></div>
<form action="{:U('/test/crop_deal')}" method="post" onsubmit="return checkCoords()" enctype="multipart/form-data" id="form">
<input type="file" name="file" onchange="change_image(this)">
<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="submit" value="裁剪"/>
</form>

下面是相关的JS代码实现:


function change_image(file){
var reader = new FileReader();
reader.onload = function(evt){
$("#target").attr('src',evt.target.result);
$('#preview').attr('src',evt.target.result);
$('#preview2').attr('src',evt.target.result);
// $('#target').css({"height":"600px","width":"600px"});
// 限制了大小会影响到截图的效果
};
reader.readAsDataURL(file.files[0]);

var jcrop_api, boundx, boundy;

setTimeout(function(){


$('#target').Jcrop({
minSize: [48,48],
setSelect: [0,0,190,190],
onChange: updatePreview,
onSelect: updatePreview,
onSelect: updateCoords,
aspectRatio: 1
},
function(){
// Use the API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the API in the jcrop_api variable
jcrop_api = this;
});

function updatePreview(c){
if (parseInt(c.w) > 0)
{
var rx = 48 / c.w; //小头像预览Div的大小
var ry = 48 / c.h;

$('#preview').css({
width: Math.round(rx * boundx) + 'px',
height: Math.round(ry * boundy) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
}
{
var rx = 199 / c.w; //大头像预览Div的大小
var ry = 199 / c.h;
$('#preview2').css({
width: Math.round(rx * boundx) + 'px',
height: Math.round(ry * boundy) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
}
};


function updateCoords(c)
{
$('#x').val(c.x);
$('#y').val(c.y);
$('#w').val(c.w);
$('#h').val(c.h);
};

},500);

}

这里有两点需要特别注意:

第一,务必在页面头部引入必要的插件资源。


  <script src="/plug/js/jquery.min.js" type="text/javascript"></script>
  <script src="/plug/js/jquery.Jcrop.min.js" type="text/javascript"></script>
  <link rel="stylesheet" href="/plug/css/Jcrop.css" rel="external nofollow" type="text/css" />

第二,细心的读者可能会发现JS代码中包含一个定时器,这看似多余,实则必要。因为图片从上传到JS加载至页面需要时间,设置定时的目的是确保图片加载完成后再初始化裁剪效果,这是经过反复测试得出的最佳实践。

该机制确保了裁剪功能在图片资源就绪后生效。

后端PHP处理逻辑

后端处理基于ThinkPHP框架,版本为3.1.3。

具体后端代码如下:


function crop_deal(){
  ob_clean();
  import ( 'ORG.Net.UploadFile' );
  $upload = new UploadFile ();
  $upload->maxSize = 2000000;
  $upload->allowExts = array (
    'jpg',
    'gif',
    'png',
    'jpeg'
  );
  $upload->savePath = './upload/test/';
  $upload->autoSub = true;
  $upload->subType = 'date';
  $upload->dateFormat = 'Ymd';
  if ($upload->upload () ) {
    $info = $upload->getUploadFileInfo();
    $new_path = "./upload/test/thumb".date('Ymd');
    $file_store = $new_path."/".date('YmdHis').".jpg";
    if(!file_exists($new_path)){
      mkdir($new_path,0777,true);
    }
    $source_path = "http://".$_SERVER['HTTP_HOST']."/upload/test/".$info[0]['savename'];
    $img_size = getimagesize($source_path);
    $width = $img_size[0];
    $height = $img_size[1];  
    $mime = $img_size['mime'];
    $srcImg = imagecreatefromstring(file_get_contents($source_path));
    $cropped_img = imagecreatetruecolor($_POST['w'], $_POST['h']);
    //缩放
    // imagecopyresampled($cropped_img,$srcImg,0,0,$_POST['x'],$_POST['y'],$_POST['w'],$_POST['h'],$width,$height);
    //裁剪
    imagecopy($cropped_img,$srcImg,0,0,$_POST['x'],$_POST['y'],$_POST['w'],$_POST['h']);
    header("Content-Type:image/jpeg");
    imagejpeg($cropped_img,$file_store);
    imagedestroy($srcImg);
    imagedestroy($cropped_img);
  }

}

此处调用了GD库中创建图像的一系列方法,其中最关键的是imagecopy() 函数。该函数依据指定的裁剪位置和大小,将原图内容复制到新图像中。这也揭示了一个重要事实:前端在用户裁剪图片时,并未直接对图片数据进行操作,而是获取裁剪时的坐标位置和尺寸,随后提交给后端进行处理。

前端仅负责计算并传递裁剪参数,后端负责实际的图像生成与保存。

总结

以上就是本文的全部内容,希望这些关于前端裁剪与后端处理的知识能对大家的开发有所帮助。如有任何疑问,欢迎留言交流,感谢支持。

作者最新文章