使用JQuery插件Jcrop进行图片截取
Jcrop插件本身并不含有图片截取功能,它仅仅是在前端层面构建一套截取动画效果并产生4个坐标点,插件使用者将这4个坐标点传回至服务器接口上进行截取操作。其优点是具有较高的通用性、浏览器兼容性(IE6+)及稳定性高,缺点是无法适用于手机H5开发(无图片缩放、拖拽效果)。
最新版的Jcrop已更新到v3.0+了,本文基于 v0.9.12,由于这版本之间API及使用方式差异非常大,故本文不具备 Jcrop v3.0+ 的使用参考价值,请读者悉知。
Jcrop V0.9+ 下载地址:http://deepliquid.com/content/Jcrop.html
Jcrop V0.9+ API中文说明:https://blog.csdn.net/xht555/article/details/43407141?utm_source=blogxgwz6
Jcrop V3.0+ 下载地址: https://github.com/tapmodo/Jcrop
html代码,这里没放出Jcrop.js、jcrop.css的引用,请读者不要漏了这关键的两步。
<div class="item">
<h3>
5、上传头像实例(预览\截取)
</h3>
<!--图片上传表单,读者也可以选择其他的上传方式-->
<form id="form_upload" enctype="multipart/form-data" action="./UploadPhoto" method="post">
<input id="File5" name="UserPhoto" type="file" value="" />
<input id="btnUpload5" type="submit" value="提交上传" />
</form> <!--截取主要内容区-->
<div id="photoWrap"> <!--截取区-->
<div id="crop_area">
<img id="crop_img" alt="头像" style="display: none"/>
</div> <!--预览区,我这里做了两个规格的预览 48*48 180*180 -->
<div id="preview_area">
<div id="preview_title">当前头像</div>
<div id="preview_small_txt">48px × 48px</div>
<div id="preview_small_wrap">
<img id="preview_small_img" alt="小预览图" src="~/Content/default_48.png"/>
</div>
<div id="preview_large_txt">180px × 180px</div>
<div id="preview_large_wrap">
<img id="preview_large_img" alt="大预览图" src="~/Content/default_180.png"/>
</div>
</div>
</div> <!--截取框坐标点数据保存区,同时也是请求后台截取接口的表单-->
<div id="crop_operation">
<form id="form_crop" action="./CropPhoto" method="post">
<input id="url" type="hidden" name="url" />
<input id="x" type="hidden" name="x" />
<input id="y" type="hidden" name="y" />
<input id="w" type="hidden" name="w" />
<input id="h" type="hidden" name="h" />
<input id="btn_crop" type="submit" value="裁剪并保存" />
</form>
</div>
</div>
JS代码,所需参数
//jcrop 所需参数
var jcrop_api;
var boundx;
var boundy; //上方是必选参数
//下方是用于截取预览图的参数,可选的
//我这里设置了48*48 180*180 两种规格的预览效果
var $pimg_small;
var $pimg_large; var xsize_small = 48;
var ysize_small = 48;
var xsize_large = 180;
var ysize_large = 180; $(function() {
$pimg_small = $('#preview_small_img');
$pimg_large = $('#preview_large_img');
});
JS代码,主体逻辑
//上传图片
$('#form_upload').ajaxForm({
dataType: "json",
data:$('#form_upload').serialize(),
success: function (data, textStatus, jqXHR) {
if (data.Status == 'success') {
//上传成功后,为主截取区、截取预览区的img赋值
$("#crop_img,#preview_small_img,#preview_large_img").attr('src', data.ImgUrl);
//用input hidden保存返回值,以便截取时使用
$("#url").val(data.ImgUrl); //if (jcrop_api != null) {
// jcrop_api.setImage(data.ImgUrl, function () {
// var bounds = jcrop_api.getBounds();
// boundx = bounds[0];
// boundy = bounds[1];
// var size = Math.min(boundx, boundy);
// jcrop_api.setSelect([0,0,size,size]);
// });
//}
return;
}
if (data.Status == 'error') {
showMessage(data.Msg);
}
},
error: function (jqXHR, textStatus, errorThrown) {
showMessage('上传失败');
console.error(textStatus);
}
}); //当图片加载完毕时,调用Jcrop初始化函数
//因为存在多次上传图片的情况,所以此处用<img/>标签的load事件,每加载完毕一次就初始化一次
$("#crop_img").load(function () {
if (jcrop_api != null) {
jcrop_api.destroy();
}
$("#crop_img").Jcrop({
onChange: updatePreview,//截取框变化事件,主要用于实时更新预览图
onSelect: updateCropData,//截取框选定事件,主要用于获得截取框的4个坐标点
aspectRatio: 1 //截取框的比例,1则是正方形
}, function () {
//$().Jcrop()初始化后的回调函数;
//这里为提高用户体验而设置了一个可选范围内最大的截取框,以告诉用户“你可以进行截取了”。
jcrop_api = this;
var bounds = this.getBounds();//获取图片实际尺寸,格式为:[w,h]
boundx = bounds[0];
boundy = bounds[1]; var size = Math.min(boundx, boundy);
jcrop_api.setSelect([0, 0, size, size]);//4个坐标点设定一个截取框
});
}); //更新预览图,这函数是官方demo给出的代码,各位可以直接copy不必深究
function updatePreview(c) {
if (parseInt(c.w) > 0) {
var rx_large = xsize_large / c.w;
var ry_large = ysize_large / c.h; $pimg_large.css({
width: Math.round(rx_large * boundx) + 'px',
height: Math.round(ry_large * boundy) + 'px',
marginLeft: '-' + Math.round(rx_large * c.x) + 'px',
marginTop: '-' + Math.round(ry_large * c.y) + 'px'
}); var rx_small = xsize_small / c.w;
var ry_small = ysize_small / c.h; $pimg_small.css({
width: Math.round(rx_small * boundx) + 'px',
height: Math.round(ry_small * boundy) + 'px',
marginLeft: '-' + Math.round(rx_small * c.x) + 'px',
marginTop: '-' + Math.round(ry_small * c.y) + 'px'
});
}
}; //截取框选定事件的处理函数,用于获取最左上角的坐标点(x、y),截取框的宽高(w、h)
function updateCropData(c) {
jQuery("#x").val(c.x);
jQuery("#y").val(c.y);
jQuery("#w").val(c.w);
jQuery("#h").val(c.h) console.group('updateCropData');
console.info(c.x)
console.info(c.y)
console.info(c.w)
console.info(c.h)
console.groupEnd('updateCropData');
} //请求后台接口,进行真正的图片截取
//因为4个坐标点是由updateCropData()函数实时更新至<form id="form_crop"/>的隐藏域里的,
//所以这里只要提交表单即可,这里是使用了jquery.form.js插件,我上一篇文章中有提到jquery.form.js的使用
$('#form_crop').ajaxForm({
dataType: "json",
success: function (data, textStatus, jqXHR) {
if (data.Status == 'success') {
showMessage('保存成功');
jcrop_api.destroy();//上传成功后释放jcrop
return;
}
if (data.Status == 'error') {
showMessage(data.Msg);
}
},
error: function (jqXHR, textStatus, errorThrown) {
showMessage('请求错误');
console.error(textStatus);
}
});
后台代码。
[HttpPost]
public ActionResult UploadPhoto()
{
HttpPostedFileBase file = Request.Files["UserPhoto"];
string contentType = file.ContentType;
string extension = Path.GetExtension(file.FileName); //检查图片格式
if (!IsAllowImg(contentType, extension))
{
return Json(new { Status = "error", Msg = "上传文件格式不符合要求。" });
} //保存形成保存路径
TimeSpan ts = DateTime.UtcNow - new DateTime(, , , , , , );
string newFileName = Convert.ToInt64(ts.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) + new Random().Next(, );
string path = Server.MapPath("~/Upload/") + newFileName + ".jpeg"; //压缩图片、转换格式(jpeg)
Image ResourceImage = Image.FromStream(file.InputStream);
if(ResourceImage.Width>)
{
int dWidth = ;
int dHeight = * ResourceImage.Height / ResourceImage.Width;
CompressPicture(file.InputStream, path, dWidth, dHeight,);
}
else
{
CompressPicture(file.InputStream, path, ResourceImage.Width, ResourceImage.Height, );
}
file.InputStream.Close(); string url = Request.ApplicationPath + "Upload/" + newFileName + ".jpeg";
return Json(new { Status = "success", Msg = "上传成功",ImgUrl= url });
} #region 压缩图像
/// <summary>
/// 无损压缩图片
/// </summary>
/// <param name="inputStream">原图片</param>
/// <param name="dFile">压缩后保存位置</param>
/// <param name="dWidth">宽度</param>
/// <param name="dHeight">高度</param>
/// <param name="flag">压缩质量 1-100</param>
/// <returns></returns>
public bool CompressPicture(Stream inputStream, string dFile, int dWidth, int dHeight, int flag)
{
System.Drawing.Image iSource = System.Drawing.Image.FromStream(inputStream);
ImageFormat tFormat = iSource.RawFormat;
int sW = , sH = ;
//按比例缩放
Size tem_size = new Size(iSource.Width, iSource.Height);
if (tem_size.Width > dWidth || tem_size.Height > dHeight)
{
if ((tem_size.Width * dHeight) > (tem_size.Height * dWidth))
{
sW = dWidth;
sH = (dWidth * tem_size.Height) / tem_size.Width;
}
else
{
sH = dHeight;
sW = (tem_size.Width * dHeight) / tem_size.Height;
}
}
else
{
sW = tem_size.Width;
sH = tem_size.Height;
} Bitmap ob = new Bitmap(dWidth, dHeight);
Graphics g = Graphics.FromImage(ob);
g.Clear(Color.WhiteSmoke);
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(iSource, new Rectangle((dWidth - sW) / , (dHeight - sH) / , sW, sH), , , iSource.Width, iSource.Height, GraphicsUnit.Pixel);
g.Dispose();
//以下代码为保存图片时,设置压缩质量
EncoderParameters ep = new EncoderParameters();
long[] qy = new long[];
qy[] = flag;//设置压缩的比例1-100
EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
ep.Param[] = eParam;
try
{
ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegICIinfo = null; for (int x = ; x < arrayICI.Length; x++)
{
if (arrayICI[x].FormatDescription.Equals("JPEG"))
{
jpegICIinfo = arrayICI[x];
break;
}
}
if (jpegICIinfo != null)
{
ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
}
else
{
ob.Save(dFile, tFormat);
}
return true;
}
catch
{
return false;
}
finally
{
iSource.Dispose();
ob.Dispose();
}
} /// <summary>
/// 无损压缩图片
/// </summary>
/// <param name="sFile">原图片</param>
/// <param name="dFile">压缩后保存位置</param>
/// <param name="dWidth">宽度</param>
/// <param name="dHeight">高度</param>
/// <param name="flag">压缩质量 1-100</param>
/// <returns></returns>
public bool CompressPicture(string sFile, string dFile, int dWidth, int dHeight, int flag)
{
System.Drawing.Image iSource = System.Drawing.Image.FromFile(sFile);
ImageFormat tFormat = iSource.RawFormat;
int sW = , sH = ;
//按比例缩放
Size tem_size = new Size(iSource.Width, iSource.Height);
if (tem_size.Width > dWidth || tem_size.Height > dHeight)
{
if ((tem_size.Width * dHeight) > (tem_size.Height * dWidth))
{
sW = dWidth;
sH = (dWidth * tem_size.Height) / tem_size.Width;
}
else
{
sH = dHeight;
sW = (tem_size.Width * dHeight) / tem_size.Height;
}
}
else
{
sW = tem_size.Width;
sH = tem_size.Height;
} Bitmap ob = new Bitmap(dWidth, dHeight);
Graphics g = Graphics.FromImage(ob);
g.Clear(Color.WhiteSmoke);
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(iSource, new Rectangle((dWidth - sW) / , (dHeight - sH) / , sW, sH), , , iSource.Width, iSource.Height, GraphicsUnit.Pixel);
g.Dispose();
//以下代码为保存图片时,设置压缩质量
EncoderParameters ep = new EncoderParameters();
long[] qy = new long[];
qy[] = flag;//设置压缩的比例1-100
EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
ep.Param[] = eParam;
try
{
ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegICIinfo = null; for (int x = ; x < arrayICI.Length; x++)
{
if (arrayICI[x].FormatDescription.Equals("JPEG"))
{
jpegICIinfo = arrayICI[x];
break;
}
}
if (jpegICIinfo != null)
{
ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
}
else
{
ob.Save(dFile, tFormat);
}
return true;
}
catch
{
return false;
}
finally
{
iSource.Dispose();
ob.Dispose();
}
} /// <summary>
/// 按指定规格裁剪图片
/// </summary>
/// <param name="sFile">源文件路径</param>
/// <param name="dFile">输出文件路径</param>
/// <param name="originPoint">裁剪区域的起点</param>
/// <param name="sSize">裁剪区域的大小</param>
/// <param name="dSize">生成的规格</param>
/// <param name="flag">压缩质量 1-100</param>
/// <returns></returns>
public bool CropPicture(string sFile, string dFile, Point originPoint , Size sSize, Size dSize, int flag)
{
System.Drawing.Image iSource = System.Drawing.Image.FromFile(sFile);
ImageFormat tFormat = iSource.RawFormat;
Bitmap ob = new Bitmap(dSize.Width, dSize.Height);
Graphics g = Graphics.FromImage(ob);
g.Clear(Color.WhiteSmoke);
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(iSource, new Rectangle(, , dSize.Width, dSize.Height), originPoint.X, originPoint.Y, sSize.Width, sSize.Height, GraphicsUnit.Pixel);
g.Dispose();
//以下代码为保存图片时,设置压缩质量
EncoderParameters ep = new EncoderParameters();
long[] qy = new long[];
qy[] = flag;//设置压缩的比例1-100
EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
ep.Param[] = eParam;
try
{
ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegICIinfo = null; for (int i = ; i < arrayICI.Length; i++)
{
if (arrayICI[i].FormatDescription.Equals("JPEG"))
{
jpegICIinfo = arrayICI[i];
break;
}
}
if(string.IsNullOrEmpty(dFile))
{
string[] temp = sFile.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
string fileName = temp[temp.Length - ];
fileName = fileName.Insert(fileName.IndexOf('.'), '_'+ dSize.Width.ToString() + '_' + dSize.Height.ToString());
temp[temp.Length - ] = fileName;
dFile = string.Empty;
foreach(string item in temp)
{
dFile += item + "\\";
}
dFile=dFile.TrimEnd('\\');
}
if (jpegICIinfo != null)
{
ob.Save(dFile, jpegICIinfo, ep);
}
else
{
ob.Save(dFile, tFormat);
}
return true;
}
catch
{
return false;
}
finally
{
iSource.Dispose();
ob.Dispose();
} }
#endregion #region 判断图片格式
public bool IsAllowImg(string contentType, string fileExtension)
{
contentType = contentType.ToLower();
if(!contentType.Contains("image"))
{
return false;
} fileExtension = fileExtension.ToLower();
string[] allowExtension = { ".bmp", ".gif", ".jpeg", ".jpg", ".png" };
foreach (string item in allowExtension)
{
if (fileExtension == item)
{
return true;
}
}
return false;
} public static bool IsAllowedExtension(HttpPostedFileBase file)
{
System.IO.Stream stream = file.InputStream;
System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
string fileclass = "";
//这里的位长要具体判断.
byte buffer;
try
{
//buffer = r.ReadByte();
//fileclass = buffer.ToString();
//buffer = r.ReadByte();
//fileclass += buffer.ToString(); for (int i = ; i < ; i++)
{
fileclass += reader.ReadByte().ToString();
} }
catch
{ }
reader.Close();
stream.Close();
if (fileclass == "" || fileclass == "")//说明255216是jpg;7173是gif;6677是BMP,13780是PNG;7790是exe,8297是rar
{
return true;
}
else
{
return false;
} }
#endregion [HttpPost]
public JsonResult CropPhoto(string url,int x,int y,int w,int h)
{
if (string.IsNullOrEmpty(url) || w == || h == )
{
return Json(new { Status = "error", Msg = "参数错误" });
} Point origin = new Point(x, y);
Size source = new Size(w, h);
Size destSmall = new Size(, );
Size destLarge = new Size(, ); bool result1 =CropPicture(Server.MapPath(url), null, origin, source, destSmall, );
bool result2 =CropPicture(Server.MapPath(url), null, origin, source, destLarge, ); var jsonResult = result1 && result2
? new { Status = "success", Msg = "操作成功" }
: new { Status = "error", Msg = "裁剪图片出现错误" }; return Json(jsonResult);
}
}
在上传图片时,我对宽度大于300px的图片进行了等比压缩,目的是控制图片在浏览器截取区内显示的比较友好。
这里也可以直接返回源图,在 <img/> 标签内使用 width属性控制图片宽度,再计算出缩放比例并将此数值存储于 <form id="form_crop" />表单内,待请求截取图片接口时将此缩放比例一并发送至后台,此时再按照缩放比例对坐标点及宽高做等比缩放计算即可截取出正确的图片。这里就提供思路,源码里我就不做这块了。
使用JQuery插件Jcrop进行图片截取的更多相关文章
- 网站开发常用jQuery插件总结(14)图片修剪插件Jcrop
一.插件功能 用于对图片进行修剪.但是在使用Jcrop时,还需要配合服务器端开发语言(如asp.net,php等)使用. 二.官方地址 http://deepliquid.com/content/Jc ...
- Web 开发最有用的50款 jQuery 插件集锦——《图片特效篇》
<Web 开发最有用的50款 jQuery 插件集锦>系列文章向大家分享最具创新的50款 jQuery 插件,这些插件分成以下类别:网页布局插件,导航插件,表格插件,滑块和转盘插件,图表插 ...
- jQuery插件slider实现图片轮播
1:引入相应的js文件 jquery.SuperSilder.js 2:HTML: 结构 注:此地加载图片的代码也可以从后台库中读取图片的集合列表,然后通过循环的方式显示出来 3:CSS 样式定义左 ...
- 对jquery插件Jcrop开发一个裁剪组件
Jcrop是一款优秀的裁剪工具,它不仅可以裁剪图像,还可以裁剪canvas及任何的div元素,具体可参考: http://code.ciaoca.com/jquery/jcrop/ 基于Jcrop,开 ...
- 图片延迟加载jquery插件imgLazyLoad(三)
此Jquery插件是在图片加载前显示一个加载图片,当图片下载完毕后显示图片出来,可对图片进行是否自动缩放功能,此Jquery插件使用时可让页面先加载,而图片后加载的方式,解决了平时使用时要在图片显示出 ...
- 插件介绍 :cropper是一款使用简单且功能强大的图片剪裁jQuery插件。
简要教程 cropper是一款使用简单且功能强大的图片剪裁jQuery插件.该图片剪裁插件支持图片放大缩小,支持鼠标滚轮操作,支持图片旋转,支持触摸屏设备,支持canvas,并且支持跨浏览器使用. c ...
- 延迟加载图片的 jQuery 插件:Lazy Load
网站的速度非常重要,现在有很多网站优化的工具,如 Google 的Page Speed,Yahoo 的 YSlow,对于网页图片,Yahoo 还提供 Smush.it这个工具对图片进行批量压缩,但是对 ...
- jQuery插件综合应用(四)头像设置
一.操作流程 会员点击头像设置,弹出一个层,在层中,有上传图片的按钮,用户点击按钮上传图片,图片在服务器端按大小压缩保存(方便剪切).保存后,在前端显示,然后用户可修剪图片.选择图片区域,点击提交,保 ...
- jQuery之Jcrop
头像裁剪是一个经常用到的功能,实现原理也较为简单,就是在本地选择好所需裁剪图片的坐标,将坐标发送到服务器,由服务器执行图片裁剪操作. jQuery插件Jcrop提供了强大的图片裁剪坐标选择插件.一下来 ...
随机推荐
- day7:vcp考试
Q121. An ESXi 6.x host in the vCenter Server inventory has disconnected due to an All Paths Down (AP ...
- 岛屿的个数12 · Number of Islands 12
[抄题]: [思维问题]: [一句话思路]: [输入量]:空: 正常情况:特大:特小:程序里处理到的特殊情况:异常情况(不合法不合理的输入): [画图]: [一刷]: [二刷]: [三刷]: [四刷] ...
- [leetcode]295. Find Median from Data Stream数据流的中位数
Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...
- 把html标签转换为实体 dhtmlspecialchars
把html标签转换为实体/*可以处理数组中的代码,他们的作用是可以把一个数组或字符串中的字符转化为html实体,可以防止页面的跨站问题,那么我们看到他的转换就是将'&','"','& ...
- 批量去重URL地址并剔除打不开网址
#coding=utf-8 import os import httplib import socket dictlist ={}; def ReadHost(): hosts = []; obn = ...
- snowflake自增ID算法 (PHP版)
/** * SnowFlake ID Generator * Based on Twitter Snowflake to generate unique ID across multiple * da ...
- db2 创建用户及授权
1.创建系统用户dbuser/ehong隶属于db2users 2.C:\Program Files\IBM\SQLLIB\BIN>db2 connect to AKZXTEST数据库连接信息 ...
- Laravel 5.4+Vue.js 初体验:Laravel下配置运行Vue.js
生产材料PHP:PHP 5.6+Laravel 5.4:https://github.com/laravel/laravel/releases/Composer:http://getcomposer. ...
- 图片素材类Web原型制作分享-Pexels
Pexels是一个高清图片下载服务站点,为用户提供海量共享图片素材的网站,每周都会定量更新. 菜单栏和底部栏都是悬浮在固定位置,内容区域滚动.首页图片排列采用瀑布流的方式,多图片滚动.包含的页面有:浏 ...
- Base64中文乱码的问题
web端和app端base64解码时中文乱码的问题. web端: String data = new BASE64Encoder().encode(data.getBytes("UTF-8& ...