前端使用Jcrop实现预览和获取图片大小,选定位置等信息。关于Jcrop,项目地址在GITHUB上,它基于MIT开源协议。本人看了下项目的源代码,感觉作者蛮认真的。Jcrop做到了兼容IE系列和其他主流浏览器,非常稳定,让开发者不再为前端方面花费太多精力。加上本人不太喜欢Flash实现,纯JavaScript实现的功能效率会更高。由于时间比较仓促,代码没有过多的优化,有点乱,下面公布前端实现和服务端处理图片部分代码。
前端实现方式如下:
#preview-pane{
background-color: white;
border: 1px solid rgba(0, 0, 0, 0.4);
border-radius: 6px;
box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
display: none;
padding: 6px;
position: absolute;
right: -160px;
top: 0;
z-index: 2000;
}
#preview-pane .preview-container {
height: 100px;
overflow: hidden;
width: 100px;
}
.cropdiv{
background: none repeat scroll 0 0 #fff;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 20px 20px rgba(0, 0, 0, 0.3);
height: auto;
left: 200px;
opacity: 0.9;
position: absolute;
top: 230px;
width: 600px;
z-index: 100;
padding:10px;
}
.cropdiv .preinfo{
float: right;
left: 500px;
position: absolute;
top: 160px;
}
.cropdiv .title{
font-size:14px;
font-weight:bold;
margin-bottom:10px;
}
.cropdiv .save{
text-align:center;
}
.cropdiv .save a{
background-color: #ff832b;
border-radius: 4px;
color: #fff;
display: inline-block;
height: 30px;
padding:2px 5px;
font-size:16px;
margin:5px;
}
var startcrop = function( imgsrc ) {
var jcrop_api, boundx, boundy, posinfo,
imgsrc_rand = imgsrc + '?' + Math.round(Math.random() * 10000);
// Grab some information about the preview pane
var $preview_html =
'
+'
+''
+'
+'
$(document.body).append($preview_html);
var $preview = $('#preview-pane'),
$pcnt = $('#preview-pane .preview-container'),
$pimg = $('#preview-pane .preview-container img'),
xsize = $pcnt.width(),
ysize = $pcnt.height();
$pimg.attr('src',imgsrc_rand);
var cropimgdiv = $('
.append(function(){
return $('
编辑头像").addClass('title');;})
.append( function(){
return $('').attr( {"src":imgsrc + '?' + Math.round(Math.random() * 10000)
,"id":"cropimg"})
})
.append(function(){
return $('
").html("保存头像").click(function(){$.ajax({
type:'POST',
url: 'handle crop url',
dataType:'json',
data:{ 'posinfo':posinfo, "boundx":boundx, "boundy":boundy },
success:function( data ) {
// do something on success
cropimgdiv.remove();
$preview.remove();
}
});
}) ).addClass('save');
})
.appendTo(document.body);
if ($("#cropimg").get(0).naturalWidth > 400) {
$("#cropimg").attr({"width":400});
JcropRun();
} else { // IE6/7/8
var image = new Image()
image.src = imgsrc_rand;
image.onload = function(){
if( image.width > 400){
$("#cropimg").attr({"width":400});
}
JcropRun();
};
}
function showCoords(c)
{
/* variables can be accessed here as
// c.x, c.y, c.x2, c.y2, c.w, c.h*/
posinfo = c;
if (parseInt(c.w) > 0) {
var rx = xsize / c.w;
var ry = ysize / c.h;
$pimg.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 JcropRun = function(){
$('#cropimg').Jcrop({
onSelect: showCoords,
bgColor: 'black',
bgOpacity: .4,
setSelect: [ 100, 100, 0, 0 ],
minSize: [ 100, 100 ],
aspectRatio: xsize / ysize
},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;
$preview.css({"display":"block"});
// Move the preview into the jcrop container for css positioning
$preview.appendTo(jcrop_api.ui.holder);
});
}
};
imagecropper方法在网上找的,写的比较差,以后有时间会整理下代码。后台图片处理方式如下:
function imagecropper($source_path, $target_width, $target_height)
{
$source_info = getimagesize($source_path);
$source_width = $source_info[0];
$source_height = $source_info[1];
$source_mime = $source_info['mime'];
$source_ratio = $source_height / $source_width;
$target_ratio = $target_height / $target_width;
// 源图过高
if ($source_ratio > $target_ratio)
{
$cropped_width = $source_width;
$cropped_height = $source_width * $target_ratio;
$source_x = 0;
$source_y = ($source_height - $cropped_height) / 2;
}
// 源图过宽
elseif ($source_ratio < $target_ratio)
{
$cropped_width = $source_height / $target_ratio;
$cropped_height = $source_height;
$source_x = ($source_width - $cropped_width) / 2;
$source_y = 0;
}
// 源图适中
else
{
$cropped_width = $source_width;
$cropped_height = $source_height;
$source_x = 0;
$source_y = 0;
}
switch ($source_mime)
{
case 'image/gif':
$source_image = imagecreatefromgif($source_path);
break;
case 'image/jpeg':
$source_image = imagecreatefromjpeg($source_path);
break;
case 'image/png':
$source_image = imagecreatefrompng($source_path);
break;
default:
return false;
break;
}
$target_image = imagecreatetruecolor($target_width, $target_height);
$cropped_image = imagecreatetruecolor($cropped_width, $cropped_height);
// 裁剪
imagecopy($cropped_image, $source_image, 0, 0, $source_x, $source_y, $cropped_width, $cropped_height);
// 缩放
imagecopyresampled($target_image, $cropped_image, 0, 0, 0, 0, $target_width, $target_height, $cropped_width, $cropped_height);
/* header('Content-Type: image/jpeg'); */
ob_start();
imagejpeg( $target_image );
return ob_get_clean();
/* imagedestroy($source_image);
imagedestroy($target_image);
imagedestroy($cropped_image);
exit; */
}
$boundx = $_POST['boundx'];
$boundy = $_POST['boundy'];
$posinfo = $_POST['posinfo'];
$realimg = '用户上传后的原图地址';
$resizeimg = imagecropper($realimg, $boundx, $boundy);
file_put_contents($realimg, $resizeimg);
/* 上面完成了图片的大小压缩,下面将图片进行裁剪 */
$source_info = getimagesize($realimg);
$source_mime = $source_info['mime'];
switch ($source_mime)
{
case 'image/gif':
$source_image = imagecreatefromgif($realimg);
break;
case 'image/jpeg':
$source_image = imagecreatefromjpeg($realimg);
break;
case 'image/png':
$source_image = imagecreatefrompng($realimg);
break;
default:
return false;
break;
}
$target_image = imagecreatetruecolor($posinfo['w'], $posinfo['h']);
$cropped_image = imagecreatetruecolor($posinfo['w'], $posinfo['h']);
imagecopy( $cropped_image, $source_image, 0, 0, $posinfo['x'], $posinfo['y'], $posinfo['w'], $posinfo['h'] );
imagecopyresampled($target_image, $cropped_image, 0, 0, 0, 0, $posinfo['w'], $posinfo['h'], $posinfo['w'], $posinfo['h']);
ob_start();
switch( $source_mime ){
case 'image/gif':
imagegif( $target_image );
break;
case 'image/jpeg':
imagejpeg( $target_image );
break;
case 'image/png':
imagepng( $target_image );
break;
default:
return false;
}
file_put_contents($realimg, ob_get_clean() );
附上运行截图: