【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 ...
随机推荐
- hdu 5154 拓扑排序
例题:hdu 5154 链接 http://acm.hdu.edu.cn/showproblem.php?pid=5154 题目意思是第一行先给出n和m表示有n件事,m个关系,接下来输入m行,每行有 ...
- PAT1066(AVL树)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...
- 分布式处理框架MapReduce的深入简出
1).MapReduce的概述 2).MapReduce 编程模型 3).MapReduce架构 4).MapReduce编程 Google MapReduce论文,论文发表于2004年 Hadoop ...
- Balanced Numbers (数位DP)
Balanced Numbers https://vjudge.net/contest/287810#problem/K Balanced numbers have been used by math ...
- 关于viewport我自己的理解
其实即使不在html中添加meta viewport标签,每个移动端浏览器都会有一个默认的viewport,只是这个viewport的宽度是980,然后做1:3或者1:2的自动缩放.所以当不在html ...
- polymorphism多态
[概念] 方法名相同,具体操作根据类不同. eg 有open()方法的ebook, kindle 都会被打开 eg 动物叫声不同 inheritance:只有superclass subclass都有 ...
- [leetcode]128. Longest Consecutive Sequence最长连续序列
Given an unsorted array of integers, find the length of the longest consecutive elements sequence. Y ...
- 36-2018 蓝桥杯Java B组试题及答案
1:第几天2000年的1月1日,是那一年的第1天.那么,2000年的5月4日,是那一年的第几天? 注意:需要提交的是一个整数,不要填写任何多余内容. 用excel算,答案125. 2.标题:方格计数 ...
- 使用JFinal实现使用MVC获取表单中的数据并将提示信息返回给另一jsp页面。
1.包结构 2.我们需要对web.xml进行配置: <?xml version="1.0" encoding="UTF-8"?> <web-a ...
- c# ?. 空值传播运算符
当左侧为空时不执行右侧代码,避免出现为null的错误,同时也避免了判断是否为null,可以和??一起连用,省了好多事.举例如下: 以前:var res=obj==null?5:obj.a; 现在:va ...