【Web】前端裁剪图片,并上传到服务器(Jcrop+canvas)
web网站中常常有的功能:上传头像、上传封面等;一般图片都有一定的比例限制,所以需要前端在上传图片时,进行裁剪,并把裁剪后的图片进行上传。
本例采用Jcrop插件实现裁剪效果,canvas裁剪图片,并把base64位的toDataURL图片转换成blob(二进制数据),最后使用XMLHttpRequest上传到服务器。
Jcrop演示及下载地址:http://code.ciaoca.com/jquery/jcrop/demo/
Jcrop的使用
本例做Jcrop的简单预览功能(同理可以实现网页的放大镜功能)
- 载入 CSS 文件
<link rel="stylesheet" href="jquery.Jcrop.css">
- 载入 JavaScript 文件
<script src="jquery.js"></script>
<script src="jquery.Jcrop.js"></script> - 给 IMG 标签加上 ID
<img id="element_id" src="pic.jpg">
- 调用 Jcrop
$('#element_id').Jcrop();
实例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图像裁剪-Jcrop</title>
<link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" />
<style>
img {
border: 0px;
}
* {
margin: 0;
padding: 0;
}
.head {
width: 600px;
height: 600px;
background-color: gray;
}
#target{
max-width: 600px;
max-height: 600px;
} #preview-pane {
position: fixed;
top: 0;
right: 0;
width: 300px;
height: 300px;
overflow: hidden;
border: 1px solid purple;
}
#preview-pane .preview-container {
width: 100%;
height: 100%;
}
#preview-pane .preview-container img{
max-width: 100%;
max-height: 100%; }
</style>
</head>
<body> <!-- 头像 -->
<div class="head" >
<img src="data:images/IMG_0109.JPG" id="target" alt="[Jcrop Example]" />
</div> <!-- 预览盒子 -->
<div id="preview-pane">
<div class="preview-container">
<img src="data:images/IMG_0109.JPG" class="jcrop-preview" alt="Preview" id="Preview"/>
</div>
</div> <script src="js/jquery.min.js"></script>
<script src="js/jquery.Jcrop.js"></script>
<script type="text/javascript"> // 定义一些使用的变量
var jcrop_api,//jcrop对象
boundx,//图片实际显示宽度
boundy,//图片实际显示高度
realWidth,// 真实图片宽度
realHeight, //真实图片高度 // 使用的jquery对象
$target = $('#target'),
$preview = $('#preview-pane'),
$pcnt = $('#preview-pane .preview-container'),
$pimg = $('#preview-pane .preview-container img'), xsize = $pcnt.width(),
ysize = $pcnt.height(); //初始化Jcrop插件
function initJcrop(){ console.log('init',[xsize,ysize]);
$target.removeAttr("style");//清空上一次初始化设置的样式
$target.Jcrop({
onChange: updatePreview,
onSelect: updatePreview,
aspectRatio: xsize / ysize
},function(){
//初始化后回调函数
// 获取图片实际显示的大小
var bounds = this.getBounds();
boundx = bounds[0];//图片实际显示宽度
boundy = bounds[1];//图片实际显示高度 // 保存jcrop_api变量
jcrop_api = this; });
} //更新显示预览内容
function updatePreview(c){
if (parseInt(c.w) > 0)
{
var rx = xsize / c.w;
var ry = ysize / c.h; $pimg.css({
maxWidth: Math.round(rx * boundx) + 'px',
maxHeight: Math.round(ry * boundy) + 'px',
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'
});
}
} window.onload = function () {
initJcrop();
}; </script>
</body>
</html>
预览效果
Canvas的使用
定义:<canvas> 标签定义图形,比如图表和其他图像。
注意:canvas标签的宽高与标签样式的宽高问题,把Canvas 比作是一个画板和一张画纸,标签宽高相当于画板,样式宽高相当于画纸。
canvas裁剪图片,准备上传
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图像裁剪-Jcrop</title>
<link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" />
<style>
img {
border: 0px;
}
* {
margin: 0;
padding: 0;
}
.head {
width: 600px;
height: 600px;
background-color: gray;
}
#target{
max-width: 600px;
max-height: 600px;
}
canvas {
position: fixed;
top: 0;
right: 0;
border: 1px solid red;
width: 200px;
height: 200px;
}
</style> </head>
<body> <!-- 头像 -->
<div class="head" >
<img src="data:images/IMG_0109.JPG" id="target" alt="[Jcrop Example]" />
</div> <!-- 画板 -->
<canvas id="myCan" width="200" height="200"></canvas> <script src="js/jquery.min.js"></script>
<script type="text/javascript"> initCanvas(); //初始化canvas画板内容
function initCanvas(){
//更新canvas画板内容
var img= document.getElementById("target");
var ct= document.getElementById("myCan");
var ctx = ct.getContext("2d"); //清空画板
ctx.clearRect(0,0, ct.width, ct.height);
//.drawImage(图像对象,原图像截取的起始X坐标,原图像截取的起始Y坐标,原图像截取的宽度,原图像截取的高度,绘制图像的起始X坐标,绘制图像的起始Y坐标,绘制图像所需要的宽度,绘制图像所需要的高度);
//矩形框[150,150,200,200]--原图像截取的起始X坐标,原图像截取的起始Y坐标,原图像截取的宽度,原图像截取的高度
ctx.drawImage(img, 150, 150, 200, 200, 0,0, ct.width , ct.height);
} </script>
</body>
</html>
预览
完整代码展示
html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图像裁剪-Jcrop</title>
<link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" />
<style>
img {
border: 0px;
}
* {
margin: 0;
padding: 0;
}
.head {
width: 600px;
height: 600px;
background-color: gray;
}
#target{
max-width: 600px;
max-height: 600px;
} #preview-pane {
position: fixed;
top: 0;
right: 0;
width: 300px;
height: 300px;
overflow: hidden;
border: 1px solid purple;
}
#preview-pane .preview-container {
width: 100%;
height: 100%; } canvas {
position: fixed;
top: 400px;
right: 0;
border: 1px solid red;
width: 200px;
height: 200px;
}
</style> </head>
<body> <!-- 头像 -->
<div class="head" >
<img src="" id="target" alt="[Jcrop Example]" />
<input type="file" id="file" onchange="changeFile()" style="display: none;"/>
</div>
<button onClick="openBrowse()">上传图片</button>
<button onClick="uploadFile()">确认</button> <!-- 预览盒子 -->
<div id="preview-pane">
<div class="preview-container">
<img src="" class="jcrop-preview" alt="Preview" id="Preview"/>
</div>
</div> <!-- 画板 -->
<canvas id="myCan" width="200" height="200"></canvas> <script src="js/jquery.min.js"></script>
<script src="js/jquery.Jcrop.js"></script>
<script type="text/javascript"> // 定义一些使用的变量
var jcrop_api,//jcrop对象
boundx,//图片实际显示宽度
boundy,//图片实际显示高度
realWidth,// 真实图片宽度
realHeight, //真实图片高度 // 使用的jquery对象
$target = $('#target'),
$preview = $('#preview-pane'),
$pcnt = $('#preview-pane .preview-container'),
$pimg = $('#preview-pane .preview-container img'), xsize = $pcnt.width(),
ysize = $pcnt.height(); //1、打开浏览器
function openBrowse(){
var ie=navigator.appName=="Microsoft Internet Explorer" ? true : false;
if(ie){
document.getElementById("file").click();
}else{
var a=document.createEvent("MouseEvents");
a.initEvent("click", true, true);
document.getElementById("file").dispatchEvent(a);
}
} //2、从 file 域获取 本地图片 url
function getFileUrl(sourceId) {
var url;
if (navigator.userAgent.indexOf("MSIE")>=1) { // IE
url = document.getElementById(sourceId).value;
} else if(navigator.userAgent.indexOf("Firefox")>0) { // Firefox
url = window.URL.createObjectURL(document.getElementById(sourceId).files.item(0));
} else if(navigator.userAgent.indexOf("Chrome")>0) { // Chrome
url = window.URL.createObjectURL(document.getElementById(sourceId).files.item(0));
} else if(navigator.userAgent.indexOf("Safari")>0) { // Chrome
url = window.URL.createObjectURL(document.getElementById(sourceId).files.item(0));
}
return url;
}
//选择文件事件
function changeFile() {
var url = getFileUrl("file");//根据id获取文件路径
preImg(url);
return false;
} //3、将本地图片 显示到浏览器上
function preImg(url) { console.log('url===' + url);
//图片裁剪逻辑
if(jcrop_api)//判断jcrop_api是否被初始化过
{
jcrop_api.destroy();
} //初始化预览div内容
initPreview();
var p = document.getElementById('Preview');
p.src = url; //初始化图片
initTarget();
var image = document.getElementById('target');
image.onload=function(){//图片加载是一个异步的过程
//获取图片文件真实宽度和大小
var img = new Image();
img.onload=function(){
realWidth = img.width;
realHeight = img.height; //获取图片真实高度之后
initJcrop();//初始化Jcrop插件
initCanvas();//初始化Canvas内容
};
img.src = url;
};
image.src = url;
} //初始化Jcrop插件
function initJcrop(){ console.log('init',[xsize,ysize]);
$target.removeAttr("style");//清空上一次初始化设置的样式
$target.Jcrop({
onChange: updatePreview,
onSelect: updatePreview,
aspectRatio: xsize / ysize
},function(){
//初始化后回调函数
// 获取图片实际显示的大小
var bounds = this.getBounds();
boundx = bounds[0];//图片实际显示宽度
boundy = bounds[1];//图片实际显示高度 // 保存jcrop_api变量
jcrop_api = this; });
} //更新显示预览内容
function updatePreview(c){
if (parseInt(c.w) > 0)
{
var rx = xsize / c.w;
var ry = ysize / c.h; $pimg.css({
maxWidth: Math.round(rx * boundx) + 'px',
maxHeight: Math.round(ry * boundy) + 'px',
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'
}); //更新canvas画板内容
var img=document.getElementById("target");
var ct=document.getElementById("myCan");
var ctx=ct.getContext("2d");
//清空画板
ctx.clearRect(0,0, ct.width, ct.height);
//.drawImage(图像对象,原图像截取的起始X坐标,原图像截取的起始Y坐标,原图像截取的宽度,原图像截取的高度,绘制图像的起始X坐标,绘制图像的起始Y坐标,绘制图像所需要的宽度,绘制图像所需要的高度);
ctx.drawImage(img, c.x/boundx * realWidth,c.y/boundy * realHeight, c.w/boundx * realWidth, c.h/boundy * realHeight,0,0, ct.width, ct.height);
}
} //初始化预览div内容
function initTarget(){
$target.removeAttr("style");//清空上一次初始化设置的样式
$target.css({
maxWidth: '100%',
maxHeight: '100%'
});
}
//初始化预览div内容
function initPreview(){
$pimg.removeAttr("style");//清空上一次初始化设置的样式
$pimg.css({
maxWidth: xsize + 'px',
maxHeight: ysize + 'px'
});
} //初始化canvas画板内容
function initCanvas(){
//更新canvas画板内容
var img= document.getElementById("target");
var ct= document.getElementById("myCan");
var ctx = ct.getContext("2d"); var myCanWidth = $('#myCan').width();
var myCanHeight = $('#myCan').height(); //清空画板
ctx.clearRect(0,0, ct.width, ct.height); //.drawImage(图像对象,原图像截取的起始X坐标,原图像截取的起始Y坐标,原图像截取的宽度,原图像截取的高度,绘制图像的起始X坐标,绘制图像的起始Y坐标,绘制图像所需要的宽度,绘制图像所需要的高度);
var dWidth = realWidth;//绘制实际宽度
var dHeight = realHeight;//绘制实际高度
if(dWidth > myCanWidth)
{
dHeight = myCanWidth / dWidth * dHeight;
dWidth = myCanWidth;
}
if(dHeight > myCanHeight)
{
dWidth = myCanHeight / dHeight * dWidth ;
dHeight = myCanHeight;
}
ctx.drawImage(img,0,0, realWidth, realHeight, 0,0, dWidth, dHeight);
} //文件上传
function uploadFile(){
//获取裁剪完后的base64图片url,转换为blob
var data=document.getElementById("myCan").toDataURL();
var formData=new FormData();
formData.append("imageName",dataURLtoBlob(data));
var httprequest= null;
if (window.XMLHttpRequest) {
httprequest = new XMLHttpRequest();
} else {
httprequest = new ActiveXObject('MicroSoft.XMLHTTP');
}
var apiurl= ""; //上传图片的api接口,自行填写
httprequest.open('POST',apiurl,true);
httprequest.send(formData);
httprequest.onreadystatechange= function () { if(httprequest.readyState == 4 ){ if(httprequest.status == 200)
{
var json=JSON.parse(httprequest.responseText);
console.log(json); }else
{
alert('获取数据错误,错误代码:' + httprequest.status + '错误信息:' + httprequest.statusText);
}
}
};
} //把base64位的toDataURL图片转换成blob
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
} window.onload = function () {
//初始化图片
preImg('images/IMG_0109.JPG');
}; </script>
</body>
</html>
图片上传接口可以参照:【Java】JavaWeb文件上传和下载
注意:canvas在裁剪图片的时候有跨域的问题,如果裁剪网络图片,会报异常:Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
本例服务端采用的方法是:服务器转发网络图片,进行图片访问。
页面上访问:<img src="img/getImg?imgUrl=http://test.example.net/a/b/c/123456.jpg"/>
服务端JAVA代码:
@RequestMapping(value = "/getImg")
public void getImg(HttpServletRequest request, HttpServletResponse response, String imgUrl) throws Exception
{
// 统一资源
URL url = new URL(imgUrl);
// 连接类的父类,抽象类
URLConnection urlConnection = url.openConnection();
// http的连接类
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
// 设定请求的方法,默认是GET
httpURLConnection.setRequestMethod("POST");
// 设置字符编码
httpURLConnection.setRequestProperty("Charset", "UTF-8");
// 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。
httpURLConnection.connect(); BufferedInputStream bin = new BufferedInputStream(httpURLConnection.getInputStream());
ServletOutputStream outputStream = response.getOutputStream(); int size = 0;
byte[] buf = new byte[1024*10];
while ((size = bin.read(buf)) != -1) {
outputStream.write(buf, 0, size);
}
bin.close();
outputStream.close();
}
预览效果
【Web】前端裁剪图片,并上传到服务器(Jcrop+canvas)的更多相关文章
- HTML5裁剪图片并上传至服务器实现原理讲解
HTML5裁剪图片并上传至服务器实现原理讲解 经常做项目需要本地上传图片裁剪并上传服务器,比如会议头像等功能,但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁 ...
- HTML5 本地裁剪图片并上传至服务器(转)
很多情况下用户上传的图片都需要经过裁剪,比如头像啊什么的.但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 ...
- 小程序踩坑记录-上传图片及canvas裁剪图片后上传至服务器
最近在写微信小程序的上传图片功能,趟过了一些坑记录一下. 想要满足的需求是,从手机端上传图片至服务器,为了避免图片过大影响传输效率,需要把图片裁剪至适当大小后再传输 主要思路是,通过wx.choose ...
- HTML5 Canvas前台压缩图片并上传到服务器
1.前台代码: <input id="fileOne" type="file" /> <input id="btnOne" ...
- js实现图片粘贴上传到服务器并展示
最近看了一些有关于js实现图片粘贴上传的demo,实现如下: (这里只能检测到截图粘贴和图片右键复制之后粘贴) demo1: document.addEventListener('paste', fu ...
- jquery photoClip支持手机端,PC端 本地裁剪图片后上传插件
支持手机,PC最好的是jquery photoClip插件,下载地址&示例:https://github.com/topoadmin/photoClip demo.html 代码: <! ...
- PHP裁剪图片并上传完整demo
日前根据功能需求,要做一个图片裁剪上传的功能,在网上找了好久,找到了这位仁兄写的demo! 下载压缩包
- Web文件(图片)上传方法
在开放Web应用程序的时候经常会遇到图片或者是文件上传的模块,这里就是该模块的实现的后台方法 上传图片方法 /// <summary> /// 功能:上传图片方法 /// </sum ...
- base64字符串转文件,以及ngImgCrop裁剪图片并上传保存到服务器示例
base64字符串是包含文件格式的文件字符串,例如:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAgAElE ...
- cropper实现基本的裁剪图片并上传
使用cropper之前需要先引用 cropper.css 和 cropper.js cropper 官网:https://fengyuanchen.github.io/cropper/ cropper ...
随机推荐
- Docker容器进入-命令行只显示-bash-4.1#
bash-4.1# cp /etc/skel/.bash* /root/ bash-4.1# su [root@4a841f025562 ~]# [root@4a841f025562 ~]# [roo ...
- 202. Happy Number (INT)
Write an algorithm to determine if a number is "happy". A happy number is a number defined ...
- 200. Number of Islands (Graph)
Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surro ...
- JAVA读取XML文件并解析获取元素、属性值、子元素信息
JAVA读取XML文件并解析获取元素.属性值.子元素信息 关键字 XML读取 InputStream DocumentBuilderFactory Element Node 前言 最 ...
- mysql定时删除6个月前的表
查看定时是否开启: 查看event是否开启 : SHOW VARIABLES LIKE '%event_sche%'; 将事件计划开启 : ; 将事件计划关闭 : ; 代码: BEGIN -- 保存表 ...
- python requests的content和text方法的区别(转)
原文地址: http://blog.csdn.net/xie_0723/article/details/51361006 问题: 一直在想requests的content和text属性的区别,从pri ...
- DialogActivity
<?xml version="1.0" encoding="utf-8"?> <resources> <style name=&q ...
- sqlserver使用SQL语句创建数据库登录对象、数据库用户以及对为该用户赋予操作权限
--创建登录名USE masterGO--PbMaster,密码123456CREATE LOGIN PbMaster with PASSWORD='1234GO --创建数据库用户USE E_Mar ...
- IIS 7.5 上传文件大小限制
上传插件:uploadify IIS版本:7.5 描述: 从IIS6升级到IIS7.5以后,网站上传文件大小被限制了,在Chrome下提示:ERR_CONNECTION_RESET,网上的各种方法都试 ...
- 已经卸载了hyper-v 仍然提示 vmware 与 hyper-v 不兼容;天天模拟器,提示VT模式没有开启,BIOS里面已经设置过了
环境win10,vm的失败和模拟器的失败都是hyper-v冲突导致的...网上看了很多千篇一律的都只是提到了卸载hyper-v,实际上我电脑仅仅卸载hyper-v是不够的. 解决办法: 卸载 hype ...