您的位置:首页 > Web前端

【Web】前端裁剪图片,并上传到服务器(Jcrop+canvas)

2017-11-07 21:37 393 查看
  web网站中常常有的功能:上传头像、上传封面等;一般图片都有一定的比例限制,所以需要前端在上传图片时,进行裁剪,并把裁剪后的图片进行上传。

  本例采用Jcrop插件实现裁剪效果,canvas裁剪图片,并把base64位的toDataURL图片转换成blob(二进制数据),最后使用XMLHttpRequest上传到服务器。

  Jcrop演示及下载地址:http://code.ciaoca.com/jquery/jcrop/demo/

Jcrop的使用

  本例做Jcrop的简单预览功能(同理可以实现网页的放大镜功能)

载入 CSS 文件

1 <link rel="stylesheet" href="jquery.Jcrop.css">


载入 JavaScript 文件

1 <script src="jquery.js"></script>
2 <script src="jquery.Jcrop.js"></script>


给 IMG 标签加上 ID

1 <img id="element_id" src="pic.jpg">


调用 Jcrop

1 $('#element_id').Jcrop();


实例代码

1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4     <meta charset="UTF-8">
5     <title>图像裁剪-Jcrop</title>
6     <link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" />
7     <style>
8         img {
9             border: 0px;
10         }
11         * {
12             margin: 0;
13             padding: 0;
14         }
15         .head {
16             width: 600px;
17             height: 600px;
18             background-color: gray;
19         }
20         #target{
21             max-width: 600px;
22             max-height: 600px;
23         }
24
25         #preview-pane {
26             position: fixed;
27             top: 0;
28             right: 0;
29             width: 300px;
30             height: 300px;
31             overflow: hidden;
32             border: 1px solid purple;
33         }
34         #preview-pane .preview-container {
35             width: 100%;
36             height: 100%;
37         }
38         #preview-pane .preview-container img{
39             max-width: 100%;
40             max-height: 100%;
41
42         }
43     </style>
44 </head>
45 <body>
46
47     <!-- 头像 -->
48     <div class="head" >
49         <img src="images/IMG_0109.JPG"  id="target" alt="[Jcrop Example]" />
50     </div>
51
52     <!-- 预览盒子 -->
53     <div id="preview-pane">
54         <div class="preview-container">
55             <img src="images/IMG_0109.JPG" class="jcrop-preview" alt="Preview"  id="Preview"/>
56         </div>
57     </div>
58
59     <script src="js/jquery.min.js"></script>
60     <script src="js/jquery.Jcrop.js"></script>
61     <script type="text/javascript">
62
63         // 定义一些使用的变量
64         var     jcrop_api,//jcrop对象
65                 boundx,//图片实际显示宽度
66                 boundy,//图片实际显示高度
67                 realWidth,// 真实图片宽度
68                 realHeight, //真实图片高度
69
70                 // 使用的jquery对象
71                 $target = $('#target'),
72                 $preview = $('#preview-pane'),
73                 $pcnt = $('#preview-pane .preview-container'),
74                 $pimg = $('#preview-pane .preview-container img'),
75
76                 xsize = $pcnt.width(),
77                 ysize = $pcnt.height();
78
79         //初始化Jcrop插件
80         function initJcrop(){
81
82             console.log('init',[xsize,ysize]);
83             $target.removeAttr("style");//清空上一次初始化设置的样式
84             $target.Jcrop({
85               onChange: updatePreview,
86               onSelect: updatePreview,
87               aspectRatio: xsize / ysize
88             },function(){
89             //初始化后回调函数
90             // 获取图片实际显示的大小
91             var bounds = this.getBounds();
92             boundx = bounds[0];//图片实际显示宽度
93             boundy = bounds[1];//图片实际显示高度
94
95             // 保存jcrop_api变量
96             jcrop_api = this;
97
98             });
99         }
100
101         //更新显示预览内容
102         function updatePreview(c){
103             if (parseInt(c.w) > 0)
104             {
105                 var rx = xsize / c.w;
106                 var ry = ysize / c.h;
107
108                 $pimg.css({
109                     maxWidth:  Math.round(rx * boundx) + 'px',
110                     maxHeight: Math.round(ry * boundy) + 'px',
111                       width: Math.round(rx * boundx) + 'px',
112                     height: Math.round(ry * boundy) + 'px',
113                     marginLeft: '-' + Math.round(rx * c.x) + 'px',
114                     marginTop: '-' + Math.round(ry * c.y) + 'px'
115                 });
116             }
117         }
118
119         window.onload = function () {
120             initJcrop();
121         };
122
123     </script>
124 </body>
125 </html>


  预览效果

    

1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4     <meta charset="UTF-8">
5     <title>图像裁剪-Jcrop</title>
6     <link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" />
7     <style>
8         img {
9             border: 0px;
10         }
11         * {
12             margin: 0;
13             padding: 0;
14         }
15         .head {
16             width: 600px;
17             height: 600px;
18             background-color: gray;
19         }
20         #target{
21             max-width: 600px;
22             max-height: 600px;
23         }
24
25         #preview-pane {
26             position: fixed;
27             top: 0;
28             right: 0;
29             width: 300px;
30             height: 300px;
31             overflow: hidden;
32             border: 1px solid purple;
33         }
34         #preview-pane .preview-container {
35             width: 100%;
36             height: 100%;
37
38         }
39
40
41         canvas {
42             position: fixed;
43             top: 400px;
44             right: 0;
45             border: 1px solid red;
46             width: 200px;
47             height: 200px;
48         }
49     </style>
50
51
52 </head>
53 <body>
54
55     <!-- 头像 -->
56     <div class="head" >
57         <img src=""  id="target" alt="[Jcrop Example]" />
58         <input type="file" id="file" onchange="changeFile()" style="display: none;"/>
59     </div>
60     <button onClick="openBrowse()">上传图片</button>
61     <button onClick="uploadFile()">确认</button>
62
63     <!-- 预览盒子 -->
64     <div id="preview-pane">
65         <div class="preview-container">
66             <img src="" class="jcrop-preview" alt="Preview"  id="Preview"/>
67         </div>
68     </div>
69
70     <!-- 画板 -->
71     <canvas id="myCan" width="200" height="200"></canvas>
72
73      <script src="js/jquery.min.js"></script>
74     <script src="js/jquery.Jcrop.js"></script>
75     <script type="text/javascript">
76
77         // 定义一些使用的变量
78         var     jcrop_api,//jcrop对象
79                 boundx,//图片实际显示宽度
80                 boundy,//图片实际显示高度
81                 realWidth,// 真实图片宽度
82                 realHeight, //真实图片高度
83
84                 // 使用的jquery对象
85                 $target = $('#target'),
86                 $preview = $('#preview-pane'),
87                 $pcnt = $('#preview-pane .preview-container'),
88                 $pimg = $('#preview-pane .preview-container img'),
89
90                 xsize = $pcnt.width(),
91                 ysize = $pcnt.height();
92
93
94
95         //1、打开浏览器
96         function openBrowse(){
97             var ie=navigator.appName=="Microsoft Internet Explorer" ? true : false;
98             if(ie){
99                 document.getElementById("file").click();
100             }else{
101                 var a=document.createEvent("MouseEvents");
102                 a.initEvent("click", true, true);
103                 document.getElementById("file").dispatchEvent(a);
104             }
105         }
106
107         //2、从 file 域获取 本地图片 url
108         function getFileUrl(sourceId) {
109             var url;
110             if (navigator.userAgent.indexOf("MSIE")>=1) { // IE
111             url = document.getElementById(sourceId).value;
112             } else if(navigator.userAgent.indexOf("Firefox")>0) { // Firefox
113             url = window.URL.createObjectURL(document.getElementById(sourceId).files.item(0));
114             } else if(navigator.userAgent.indexOf("Chrome")>0) { // Chrome
115             url = window.URL.createObjectURL(document.getElementById(sourceId).files.item(0));
116             } else if(navigator.userAgent.indexOf("Safari")>0) { // Chrome
117             url = window.URL.createObjectURL(document.getElementById(sourceId).files.item(0));
118             }
119             return url;
120         }
121         //选择文件事件
122         function changeFile() {
123             var url = getFileUrl("file");//根据id获取文件路径
124             preImg(url);
125             return false;
126         }
127
128         //3、将本地图片 显示到浏览器上
129         function preImg(url) {
130
131             console.log('url===' + url);
132             //图片裁剪逻辑
133             if(jcrop_api)//判断jcrop_api是否被初始化过
134             {
135                 jcrop_api.destroy();
136             }
137
138             //初始化预览div内容
139             initPreview();
140             var p = document.getElementById('Preview');
141             p.src = url;
142
143             //初始化图片
144             initTarget();
145             var image = document.getElementById('target');
146             image.onload=function(){//图片加载是一个异步的过程
147                     //获取图片文件真实宽度和大小
148                     var img = new Image();
149                     img.onload=function(){
150                         realWidth = img.width;
151                         realHeight = img.height;
152
153                         //获取图片真实高度之后
154                         initJcrop();//初始化Jcrop插件
155                         initCanvas();//初始化Canvas内容
156                     };
157                     img.src = url;
158             };
159             image.src = url;
160         }
161
162         //初始化Jcrop插件
163         function initJcrop(){
164
165             console.log('init',[xsize,ysize]);
166             $target.removeAttr("style");//清空上一次初始化设置的样式
167             $target.Jcrop({
168               onChange: updatePreview,
169               onSelect: updatePreview,
170               aspectRatio: xsize / ysize
171             },function(){
172             //初始化后回调函数
173             // 获取图片实际显示的大小
174             var bounds = this.getBounds();
175             boundx = bounds[0];//图片实际显示宽度
176             boundy = bounds[1];//图片实际显示高度
177
178             // 保存jcrop_api变量
179             jcrop_api = this;
180
181             });
182         }
183
184
185         //更新显示预览内容
186         function updatePreview(c){
187             if (parseInt(c.w) > 0)
188             {
189                 var rx = xsize / c.w;
190                 var ry = ysize / c.h;
191
192                 $pimg.css({
193                     maxWidth:  Math.round(rx * boundx) + 'px',
194                     maxHeight: Math.round(ry * boundy) + 'px',
195                       width: Math.round(rx * boundx) + 'px',
196                     height: Math.round(ry * boundy) + 'px',
197                     marginLeft: '-' + Math.round(rx * c.x) + 'px',
198                     marginTop: '-' + Math.round(ry * c.y) + 'px'
199                 });
200
201                 //更新canvas画板内容
202                 var img=document.getElementById("target");
203                 var ct=document.getElementById("myCan");
204                 var ctx=ct.getContext("2d");
205                 //清空画板
206                 ctx.clearRect(0,0, ct.width, ct.height);
207                 //.drawImage(图像对象,原图像截取的起始X坐标,原图像截取的起始Y坐标,原图像截取的宽度,原图像截取的高度,绘制图像的起始X坐标,绘制图像的起始Y坐标,绘制图像所需要的宽度,绘制图像所需要的高度);
208                 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);
209             }
210         }
211
212         //初始化预览div内容
213         function initTarget(){
214             $target.removeAttr("style");//清空上一次初始化设置的样式
215             $target.css({
216                   maxWidth:  '100%',
217                 maxHeight: '100%'
218               });
219         }
220         //初始化预览div内容
221         function initPreview(){
222             $pimg.removeAttr("style");//清空上一次初始化设置的样式
223             $pimg.css({
224                   maxWidth:  xsize + 'px',
225                 maxHeight: ysize + 'px'
226               });
227         }
228
229         //初始化canvas画板内容
230         function initCanvas(){
231             //更新canvas画板内容
232             var img= document.getElementById("target");
233             var ct= document.getElementById("myCan");
234             var ctx = ct.getContext("2d");
235
236             var myCanWidth = $('#myCan').width();
237             var myCanHeight = $('#myCan').height();
238
239             //清空画板
240             ctx.clearRect(0,0, ct.width, ct.height);
241
242              //.drawImage(图像对象,原图像截取的起始X坐标,原图像截取的起始Y坐标,原图像截取的宽度,原图像截取的高度,绘制图像的起始X坐标,绘制图像的起始Y坐标,绘制图像所需要的宽度,绘制图像所需要的高度);
243             var dWidth = realWidth;//绘制实际宽度
244             var dHeight = realHeight;//绘制实际高度
245             if(dWidth > myCanWidth)
246             {
247                 dHeight = myCanWidth / dWidth *  dHeight;
248                 dWidth = myCanWidth;
249             }
250             if(dHeight > myCanHeight)
251             {
252                 dWidth = myCanHeight / dHeight * dWidth ;
253                 dHeight = myCanHeight;
254             }
255             ctx.drawImage(img,0,0, realWidth, realHeight, 0,0,  dWidth, dHeight);
256         }
257
258         //文件上传
259         function uploadFile(){
260             //获取裁剪完后的base64图片url,转换为blob
261             var data=document.getElementById("myCan").toDataURL();
262             var formData=new FormData();
263             formData.append("imageName",dataURLtoBlob(data));
264             var httprequest= null;
265             if (window.XMLHttpRequest) {
266                 httprequest = new XMLHttpRequest();
267             } else {
268                 httprequest = new ActiveXObject('MicroSoft.XMLHTTP');
269             }
270             var apiurl= ""; //上传图片的api接口,自行填写
271             httprequest.open('POST',apiurl,true);
272             httprequest.send(formData);
273             httprequest.onreadystatechange= function () {
274
275                 if(httprequest.readyState == 4 ){
276
277                     if(httprequest.status == 200)
278                     {
279                         var json=JSON.parse(httprequest.responseText);
280                         console.log(json);
281
282                     }else
283                     {
284                         alert('获取数据错误,错误代码:' + httprequest.status + '错误信息:' + httprequest.statusText);
285                     }
286                 }
287             };
288         }
289
290         //把base64位的toDataURL图片转换成blob
291         function dataURLtoBlob(dataurl) {
292             var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
293                     bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
294             while (n--) {
295                 u8arr
= bstr.charCodeAt(n);
296             }
297             return new Blob([u8arr], { type: mime });
298         }
299
300         window.onload = function () {
301             //初始化图片
302             preImg('images/IMG_0109.JPG');
303         };
304
305     </script>
306 </body>
307 </html>


View Code
  图片上传接口可以参照:【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代码:

1 @RequestMapping(value = "/getImg")
2     public void getImg(HttpServletRequest request, HttpServletResponse response, String imgUrl) throws Exception
3     {
4         // 统一资源
5         URL url = new URL(imgUrl);
6         // 连接类的父类,抽象类
7         URLConnection urlConnection = url.openConnection();
8         // http的连接类
9         HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
10         // 设定请求的方法,默认是GET
11         httpURLConnection.setRequestMethod("POST");
12         // 设置字符编码
13         httpURLConnection.setRequestProperty("Charset", "UTF-8");
14         // 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。
15         httpURLConnection.connect();
16
17         BufferedInputStream bin = new BufferedInputStream(httpURLConnection.getInputStream());
18         ServletOutputStream outputStream = response.getOutputStream();
19
20         int size = 0;
21         byte[] buf = new byte[1024*10];
22         while ((size = bin.read(buf)) != -1) {
23             outputStream.write(buf, 0, size);
24         }
25         bin.close();
26         outputStream.close();
27     }


  预览效果

    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: