基于canvas和jsp的头像剪辑上传

最近在做项目时候需要一个头像长传功能,但是现在照片动不动就几兆的,都是流量的浪费。

我只是简单想要上传一个头像而已。。。

经过几天发愤图强。。总算是略有所获。。

基本思路:

1、html部分,图片剪辑功能。主要就是整个图片选择一块,可以选取某一块,调整大小等

2、将选择的图片画在canvas中。当点击上传时候,将图片转化成base64格式,传给后台jsp页面

3、jsp将base64的格式的图片转化成文件格式存在服务器里(当然,直接将字符串存入数据库也可以)

效果如下:

生成图片:

html代码如下:

<!doctype html>
<html>
<head>
<style type="text/css">
body{background:#888;}
#box{left:200px;top:100px;position:absolute;}
#imgBox{position:absolute;left:0px;top:0px;}
#imgBox img{opacity:0.5;}
#clipBox img{clip:rect(0px,200px,200px,0px);position:absolute;}
#clipDiv{position:absolute;left:0px;top:0px;width:200px;height:200px;border:1px solid #fff;cursor:move;}
#clipDiv div{position:absolute;width:8px;height:8px;background:#FFF;margin-left:-4px;margin-top:-4px;}
#clipDiv :nth-child(1){left:0px;top:0px;cursor:nw-resize;}
#clipDiv :nth-child(2){left:50%;top:0px;cursor:n-resize;}
#clipDiv :nth-child(3){left:100%;top:0px;cursor:ne-resize;}
#clipDiv :nth-child(4){left:100%;top:50%;cursor:e-resize;}
#clipDiv :nth-child(5){left:100%;top:100%;cursor:se-resize;}
#clipDiv :nth-child(6){left:50%;top:100%;cursor:s-resize;}
#clipDiv :nth-child(7){left:0px;top:100%;cursor:sw-resize;}
#clipDiv :nth-child(8){left:0px;top:50%;cursor:w-resize;}
#photoBox{position:absolute;left:900px;top:100px;width:200px;height:200px;}
#photoBox #photo{position:absolute;}
#submit{position:absolute;left:200px;top:40px;width:100px;height:40px;line-height:40px;text-align:center;border:solid 1px #000;cursor:pointer;border-radius:4px;}
#res{position:absolute;left:320px;top:40px;width:500px;height:40px;line-height:40px;text-align:center;border:solid 1px #000;cursor:pointer;border-radius:4px;}
</style>
</head>
<body>
<div id="submit">submit</div>
<div id="res"></div>
<div id="box">
    <div id="imgBox"></div>
    <div id="clipBox"></div>
    <div id="clipDiv"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
</div>
<div id="photoBox"><canvas id="photo" width='200' height='200' style='border:solid #000 1px;'></canvas></div>
<script>
var CLIP_WIDTH = 200 ;//头像宽度
var CLIP_HEIGHT = 200 ;//头像高度
var maxWidth = 0;//引用图片宽度
var maxHeight = 0 ;//引用图片高度

var box = $('clipDiv') ;//选取框层
var clipImg = $('clipBox') ; //选取图片层
var canvas = $('photo') ;//canvas层
var photo = canvas.getContext('2d') ;

var elem = -1 ; //当前选择元素
var boxLeft = 0 ;
var boxTop = 0 ;
var boxWidth = 0 ;
var boxHeight = 0 ;
var mouseX = 0 ;
var mouseY = 0 ;

var img = new Image() ;
img.src = '1.jpg' ;//原始图片
img.onload = funInit ;
$('submit').onclick = funUpdateImg ;

//图片剪辑

for(var i  = 0 ; i < box.childNodes.length ; i ++){
    box.childNodes[i].index = i ;
    box.childNodes[i].onmousedown = function(e){
        elem = this.index ;
        mouseX = e.clientX ;
        mouseY = e.clientY ;
        boxWidth = box.offsetWidth-2 ;
        boxHeight = box.offsetHeight-2 ;
        boxLeft = box.offsetLeft ;
        boxTop = box.offsetTop ;
        e.cancelBubble = true;
    }
}
box.onmousedown = function(e){
    elem = 8 ;
    mouseX = e.clientX ;
    mouseY = e.clientY ;
    boxWidth = box.offsetWidth-2 ;
    boxHeight = box.offsetHeight-2 ;
    boxLeft = box.offsetLeft ;
    boxTop = box.offsetTop ;
}

window.onmousemove = function(e){
    if(elem == -1)return ;
    var x = e.clientX ;
    var y = e.clientY ;
    var curLeft = boxLeft ;
    var curTop = boxTop ;
    var curWidth = boxWidth ;
    var curHeight = boxHeight ;
    switch(elem){
        case 0:
            curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
            curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
            curWidth = boxLeft+boxWidth-curLeft ;
            curHeight = boxTop +boxHeight-curTop ;
            break;
        case 1:
            curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
            curHeight = boxTop +boxHeight-curTop ;
            break;
        case 2:
            curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
            curHeight = boxTop +boxHeight-curTop ;
            curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
            break;
        case 3:
            curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
            break;
        case 4:
            curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
            curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
            break;
        case 5:
            curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
            break;
        case 6:
            curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
            curWidth = boxLeft+boxWidth-curLeft ;
            curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
            break;
        case 7:
            curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
            curWidth = boxLeft+boxWidth-curLeft ;
            break;
        case 8:
            curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,maxWidth-boxWidth)) ;
            curTop = Math.max(0,Math.min(boxTop + y - mouseY,maxHeight-boxHeight)) ;
            break; 
    }
    box.style.left = curLeft + 'px' ;
    box.style.top = curTop + 'px' ;
    box.style.width = curWidth + 'px' ;
    box.style.height = curHeight + 'px' ;
    clipImg.childNodes[0].style.clip = "rect("+curTop+"px,"+(curLeft+curWidth)+"px,"+(curTop+curHeight)+"px,"+(curLeft)+"px)" ;
    showPhoto(curLeft,curTop,curWidth,curHeight) ;
}
window.onmouseup = function(){
    elem = -1 ;
}

//将选中的图片画在canvas上
function showPhoto(left,top,width,height){
    photo.clearRect(0,0,CLIP_WIDTH,CLIP_HEIGHT) ;
    photo.drawImage(img,-left*CLIP_WIDTH/width,-top*CLIP_HEIGHT/height,maxWidth*CLIP_WIDTH/width,maxHeight*CLIP_HEIGHT/height);
}
//获取base64格式的png图片内容
function funGetImg(){
    var data = canvas.toDataURL("image/png") ;
    data = data.replace(/+/g,"#") ;//后台java代码中加号出问题
    return data ;
}
//post方式将内容传给后台
function ajaxSendImg(str,callback){
    var xmlhttp = new XMLHttpRequest() ;
    xmlhttp.open("post","base64toimg.jsp",false);
    xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 
    xmlhttp.send(str);
    callback.call(null,xmlhttp.responseText) ;
}

function funUpdateImg(){
    var data = funGetImg() ;
    var url = "imgStr="+data.substring(22) ;
    ajaxSendImg(url,log);
}

function $(id){
    return document.getElementById(id) ;
}

function log(){
    $('res').innerHTML = arguments[0] ;
}

function funInit(){
    maxWidth = this.width ;
    maxHeight= this.height ;
    $('clipBox').appendChild(img) ;
    var newImg = new  Image() ;
    newImg.src = this.src ;
    $('imgBox').appendChild(newImg);
    showPhoto(0,0,CLIP_WIDTH,CLIP_HEIGHT);
}
</script>
</body>
</html>
jsp代码:
  1 <!doctype html>
  2 <html>
  3 <head>
  4 <style type="text/css">
  5 body{background:#888;}
  6 #box{left:200px;top:100px;position:absolute;}
  7 #imgBox{position:absolute;left:0px;top:0px;}
  8 #imgBox img{opacity:0.5;}
  9 #clipBox img{clip:rect(0px,200px,200px,0px);position:absolute;}
 10 #clipDiv{position:absolute;left:0px;top:0px;width:200px;height:200px;border:1px solid #fff;cursor:move;}
 11 #clipDiv div{position:absolute;width:8px;height:8px;background:#FFF;margin-left:-4px;margin-top:-4px;}
 12 #clipDiv :nth-child(1){left:0px;top:0px;cursor:nw-resize;}
 13 #clipDiv :nth-child(2){left:50%;top:0px;cursor:n-resize;}
 14 #clipDiv :nth-child(3){left:100%;top:0px;cursor:ne-resize;}
 15 #clipDiv :nth-child(4){left:100%;top:50%;cursor:e-resize;}
 16 #clipDiv :nth-child(5){left:100%;top:100%;cursor:se-resize;}
 17 #clipDiv :nth-child(6){left:50%;top:100%;cursor:s-resize;}
 18 #clipDiv :nth-child(7){left:0px;top:100%;cursor:sw-resize;}
 19 #clipDiv :nth-child(8){left:0px;top:50%;cursor:w-resize;}
 20 #photoBox{position:absolute;left:900px;top:100px;width:200px;height:200px;}
 21 #photoBox #photo{position:absolute;}
 22 #submit{position:absolute;left:200px;top:40px;width:100px;height:40px;line-height:40px;text-align:center;border:solid 1px #000;cursor:pointer;border-radius:4px;}
 23 #res{position:absolute;left:320px;top:40px;width:500px;height:40px;line-height:40px;text-align:center;border:solid 1px #000;cursor:pointer;border-radius:4px;}
 24 </style>
 25 </head>
 26 <body>
 27 <div id="submit">submit</div>
 28 <div id="res"></div>
 29 <div id="box">
 30     <div id="imgBox"></div>
 31     <div id="clipBox"></div>
 32     <div id="clipDiv"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
 33 </div>
 34 <div id="photoBox"><canvas id="photo" width='200' height='200' style='border:solid #000 1px;'></canvas></div>
 35 <script>
 36 var CLIP_WIDTH = 200 ;//头像宽度
 37 var CLIP_HEIGHT = 200 ;//头像高度
 38 var maxWidth = 0;//引用图片宽度
 39 var maxHeight = 0 ;//引用图片高度
 40 
 41 var box = $('clipDiv') ;//选取框层
 42 var clipImg = $('clipBox') ; //选取图片层
 43 var canvas = $('photo') ;//canvas层
 44 var photo = canvas.getContext('2d') ;
 45 
 46 var elem = -1 ; //当前选择元素
 47 var boxLeft = 0 ;
 48 var boxTop = 0 ;
 49 var boxWidth = 0 ;
 50 var boxHeight = 0 ;
 51 var mouseX = 0 ;
 52 var mouseY = 0 ;
 53 
 54 var img = new Image() ;
 55 img.src = '1.jpg' ;//原始图片
 56 img.onload = funInit ;
 57 $('submit').onclick = funUpdateImg ;
 58 
 59 //图片剪辑
 60 
 61 for(var i  = 0 ; i < box.childNodes.length ; i ++){
 62     box.childNodes[i].index = i ;
 63     box.childNodes[i].onmousedown = function(e){
 64         elem = this.index ;
 65         mouseX = e.clientX ;
 66         mouseY = e.clientY ;
 67         boxWidth = box.offsetWidth-2 ;
 68         boxHeight = box.offsetHeight-2 ;
 69         boxLeft = box.offsetLeft ;
 70         boxTop = box.offsetTop ;
 71         e.cancelBubble = true;
 72     }
 73 }
 74 box.onmousedown = function(e){
 75     elem = 8 ;
 76     mouseX = e.clientX ;
 77     mouseY = e.clientY ;
 78     boxWidth = box.offsetWidth-2 ;
 79     boxHeight = box.offsetHeight-2 ;
 80     boxLeft = box.offsetLeft ;
 81     boxTop = box.offsetTop ;
 82 }
 83 
 84 window.onmousemove = function(e){
 85     if(elem == -1)return ;
 86     var x = e.clientX ;
 87     var y = e.clientY ;
 88     var curLeft = boxLeft ;
 89     var curTop = boxTop ;
 90     var curWidth = boxWidth ;
 91     var curHeight = boxHeight ;
 92     switch(elem){
 93         case 0:
 94             curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
 95             curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
 96             curWidth = boxLeft+boxWidth-curLeft ;
 97             curHeight = boxTop +boxHeight-curTop ;
 98             break;
 99         case 1:
100             curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
101             curHeight = boxTop +boxHeight-curTop ;
102             break;
103         case 2:
104             curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
105             curHeight = boxTop +boxHeight-curTop ;
106             curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
107             break;
108         case 3:
109             curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
110             break;
111         case 4:
112             curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
113             curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
114             break;
115         case 5:
116             curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
117             break;
118         case 6:
119             curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
120             curWidth = boxLeft+boxWidth-curLeft ;
121             curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
122             break;
123         case 7:
124             curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
125             curWidth = boxLeft+boxWidth-curLeft ;
126             break;
127         case 8:
128             curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,maxWidth-boxWidth)) ;
129             curTop = Math.max(0,Math.min(boxTop + y - mouseY,maxHeight-boxHeight)) ;
130             break; 
131     }
132     box.style.left = curLeft + 'px' ;
133     box.style.top = curTop + 'px' ;
134     box.style.width = curWidth + 'px' ;
135     box.style.height = curHeight + 'px' ;
136     clipImg.childNodes[0].style.clip = "rect("+curTop+"px,"+(curLeft+curWidth)+"px,"+(curTop+curHeight)+"px,"+(curLeft)+"px)" ;
137     showPhoto(curLeft,curTop,curWidth,curHeight) ;
138 }
139 window.onmouseup = function(){
140     elem = -1 ;
141 }
142 
143 //将选中的图片画在canvas上
144 function showPhoto(left,top,width,height){
145     photo.clearRect(0,0,CLIP_WIDTH,CLIP_HEIGHT) ;
146     photo.drawImage(img,-left*CLIP_WIDTH/width,-top*CLIP_HEIGHT/height,maxWidth*CLIP_WIDTH/width,maxHeight*CLIP_HEIGHT/height);
147 }
148 //获取base64格式的png图片内容
149 function funGetImg(){
150     var data = canvas.toDataURL("image/png") ;
151     data = data.replace(/+/g,"#") ;//后台java代码中加号出问题
152     return data ;
153 }
154 //post方式将内容传给后台
155 function ajaxSendImg(str,callback){
156     var xmlhttp = new XMLHttpRequest() ;
157     xmlhttp.open("post","base64toimg.jsp",false);
158     xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 
159     xmlhttp.send(str);
160     callback.call(null,xmlhttp.responseText) ;
161 }
162 
163 function funUpdateImg(){
164     var data = funGetImg() ;
165     var url = "imgStr="+data.substring(22) ;
166     ajaxSendImg(url,log);
167 }
168 
169 function $(id){
170     return document.getElementById(id) ;
171 }
172 
173 function log(){
174     $('res').innerHTML = arguments[0] ;
175 }
176 
177 function funInit(){
178     maxWidth = this.width ;
179     maxHeight= this.height ;
180     $('clipBox').appendChild(img) ;
181     var newImg = new  Image() ;
182     newImg.src = this.src ;
183     $('imgBox').appendChild(newImg);
184     showPhoto(0,0,CLIP_WIDTH,CLIP_HEIGHT);
185 }
186 </script>
187 </body>
188 </html
 1 <%@page contentType="text/html;charset=utf-8"%>
 2 <%@page import="java.io.*,sun.misc.BASE64Decoder,sun.misc.BASE64Encoder"%>
 3 <%
 4     String imgStr = request.getParameter("imgStr");
 5     imgStr = imgStr.replaceAll("#","+");
 6     BASE64Decoder decoder = new BASE64Decoder();
 7     try{
 8         byte[] b = decoder.decodeBuffer(imgStr);
 9         String relPath = application.getRealPath("/") ;
10         String path = "/upload/photo.png" ;
11         File f = new File(relPath + path);
12         OutputStream os = new FileOutputStream(f);    
13         os.write(b);
14         os.flush();
15         os.close();
16         out.println(path);
17     } 
18     catch (Exception e) 
19     {
20         out.println("error");
21     }
22 %>

将base64图片内容传给jsp时候。老是会出错。发现是因为“+”传过去就解析成其他符号了。。一直想不明白。。

只能暂时将“+”缓存“#”,到jsp之后在repalce过来,如果有人知道是怎么回事,希望告知下。。

欢迎讨论,转载请注明出处。谢谢!

原文地址:https://www.cnblogs.com/shb190802/p/4050098.html