图片裁剪工具——JCorp

需求:用户上传或者修改头像的时候先将图片裁剪,固定宽度和高度,这样在不同的情景下显示的时候不会出现压缩失真。

中间折腾过的方法:

1.smartCorp.js

国外一个大神写的,根据图像的饱和度裁剪最好看的照片,刚开始以为很好用的,在官网上下载了源码,demo跑起来还可以,但是裁剪成小图片的时候裁剪不了,项目是Java的,但是demo用的是PHP,我也不会PHP,也没有运行环境,最后放弃了。

2.JS素材网上下载的插件。也是一样的问题,裁剪成小图片的后台代码运行不了,而且样式也不好看,还是选择放弃。

3.JCorp.js 这也是国外的开源软件,第一眼看上去清新大方,有点意思。还有详尽的使用方法,不错不错。但是最核心的裁剪问题依然存在。有博客上用的是后台的Java代码裁剪,demo支持直接本地读取,和写入,没有问题,但是放在网页上,图片走服务器上传是很麻烦的一个问题,除了上传原图,还要返回裁剪后的图片base64码,这样子显示是没问题了 ,但是怎么上传到阿里云服务器又是问题了。找啊找,终于找到一个博客写的是用前端H5的<canvas>画布裁剪,不走服务器,很nice。于是乎直接放在项目里用了,集成好也没问题,很开心。开心了一分钟,然后,流文件怎么上传到阿里云服务器呢,翻遍了阿里云的社区和手册也没找到答案。然后简书上的一篇文章讲清楚了要怎么处理上传,搬过来,解决好了。最后还有一个问题,如何上传到网易云呢?翻了网易云的开发文档,用断点走了几遍js文件,找到了上传的文件格式,一遍一遍的试,最后也搞好了。超级超级开心的。以下是实现代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!doctype html>  
<html>  
<head>  
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>  
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/>  
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>  
  <meta name="description" id="description1" content="1">  
  <meta name="renderer" content="webkit">  
  <meta name="format-detection" content="telephone=no">  
  <title>图片上传</title>  
  
  
    <style type="text/css">  
    
    .jcrop-holder {  
        direction: ltr;  
        text-align: center;  
        margin: 0 auto;  
        /* IE10 touch compatibility */  
        -ms-touch-action: none;  
    }  
        /* Selection Border */  
    .jcrop-vline,  
    .jcrop-hline {  
        background: #ffffff url("Jcrop.gif");  
        font-size: 0;  
        position: absolute;  
    }  
    .jcrop-vline {  
        height: 100%;  
        width: 1px !important;  
    }  
    .jcrop-vline.right {  
        right: 0;  
    }  
    .jcrop-hline {  
        height: 1px !important;  
        width: 100%;  
    }  
    .jcrop-hline.bottom {  
        bottom: 0;  
    }  
        /* Invisible click targets */  
    .jcrop-tracker {  
        height: 100%;  
        width: 100%;  
        /* "turn off" link highlight */  
        -webkit-tap-highlight-color: transparent;  
        /* disable callout, image save panel */  
        -webkit-touch-callout: none;  
        /* disable cut copy paste */  
        -webkit-user-select: none;  
    }  
        /* Selection Handles */  
    .jcrop-handle {  
        background-color: #333333;  
        border: 1px #eeeeee solid;  
        width: 7px;  
        height: 7px;  
        font-size: 1px;  
    }  
    .jcrop-handle.ord-n {  
        left: 50%;  
        margin-left: -4px;  
        margin-top: -4px;  
        top: 0;  
    }  
    .jcrop-handle.ord-s {  
        bottom: 0;  
        left: 50%;  
        margin-bottom: -4px;  
        margin-left: -4px;  
    }  
    .jcrop-handle.ord-e {  
        margin-right: -4px;  
        margin-top: -4px;  
        right: 0;  
        top: 50%;  
    }  
    .jcrop-handle.ord-w {  
        left: 0;  
        margin-left: -4px;  
        margin-top: -4px;  
        top: 50%;  
    }  
    .jcrop-handle.ord-nw {  
        left: 0;  
        margin-left: -4px;  
        margin-top: -4px;  
        top: 0;  
    }  
    .jcrop-handle.ord-ne {  
        margin-right: -4px;  
        margin-top: -4px;  
        right: 0;  
        top: 0;  
    }  
    .jcrop-handle.ord-se {  
        bottom: 0;  
        margin-bottom: -4px;  
        margin-right: -4px;  
        right: 0;  
    }  
    .jcrop-handle.ord-sw {  
        bottom: 0;  
        left: 0;  
        margin-bottom: -4px;  
        margin-left: -4px;  
    }  
        /* Dragbars */  
    .jcrop-dragbar.ord-n,  
    .jcrop-dragbar.ord-s {  
        height: 7px;  
        width: 100%;  
    }  
    .jcrop-dragbar.ord-e,  
    .jcrop-dragbar.ord-w {  
        height: 100%;  
        width: 7px;  
    }  
    .jcrop-dragbar.ord-n {  
        margin-top: -4px;  
    }  
    .jcrop-dragbar.ord-s {  
        bottom: 0;  
        margin-bottom: -4px;  
    }  
    .jcrop-dragbar.ord-e {  
        margin-right: -4px;  
        right: 0;  
    }  
    .jcrop-dragbar.ord-w {  
        margin-left: -4px;  
    }  
        /* The "jcrop-light" class/extension */  
    .jcrop-light .jcrop-vline,  
    .jcrop-light .jcrop-hline {  
        background: #ffffff;  
        filter: alpha(opacity=70) !important;  
        opacity: .70!important;  
    }  
    .jcrop-light .jcrop-handle {  
        -moz-border-radius: 3px;  
        -webkit-border-radius: 3px;  
        background-color: #000000;  
        border-color: #ffffff;  
        border-radius: 3px;  
    }  
        /* The "jcrop-dark" class/extension */  
    .jcrop-dark .jcrop-vline,  
    .jcrop-dark .jcrop-hline {  
        background: #000000;  
        filter: alpha(opacity=70) !important;  
        opacity: 0.7 !important;  
    }  
    .jcrop-dark .jcrop-handle {  
        -moz-border-radius: 3px;  
        -webkit-border-radius: 3px;  
        background-color: #ffffff;  
        border-color: #000000;  
        border-radius: 3px;  
    }  
        /* Simple macro to turn off the antlines */  
    .solid-line .jcrop-vline,  
    .solid-line .jcrop-hline {  
        background: #ffffff;  
    }  
        /* Fix for twitter bootstrap et al. */  
    .jcrop-holder img,  
    img.jcrop-preview {  
        max-width: none;  
    }  
        .uploadPics {  
            position: relative;  
            width: 380px;  
            background-color: #fff;  
            height: 460px;  
            overflow: hidden;  
        }  
  
        .uploadPics > img {  
            position: absolute;  
            top: 20px;  
            right: 10px;  
            cursor: pointer;  
        }  
  
        .uploadPics .picTil {  
            padding: 20px;  
            font-size: 16px;  
            color: #323232;  
            border-bottom: 1px solid #f3f3f3;  
        }  
  
        .uploadPics .picCont {  
            margin: 20px;  
            padding: 15px;  
            width: 300px;  
            height: 337px;  
            background-color: #f2f2f5;  
        }  
  
        .uploadPics .picCont > p {  
            margin-top: 20px;  
            text-align: center;  
        }  
  
  
        .uploadPics .picFooter {  
            text-align: center;  
        }  
  
        .uploadPics .picFooter{  
            display: inline-block;  
            margin: 20px;  
            width: 130px;  
            height: 35px;  
            font-size: 18px;  
            line-height: 35px;  
            color: #fff;  
            border-radius: 5px;  
            cursor: pointer;  
        }  
  
        .uploadPics .picFooter .upload {  
            background-color: #aaa;  
        }  
  
        .uploadPics .picFooter .confirm {  
            background-color: #ed2828;  
        }  
        #myCan{  
            position: absolute;  
            top: 86px;  
            right: 110px;  
        } 
        .info{
        	 position: absolute;  
            top: 16px;  
            right: 196px;  
        }
    </style>  
    <link rel="stylesheet" href="<%=request.getContextPath()%>/Jcrop/css/jquery.Jcrop.css" type="text/css" />
    <script type="text/javascript" src="<%=request.getContextPath()%>/Jcrop/js/jquery.Jcrop.js"></script>
</head>  
<body>  
<div id="showbg" style="display: none;"> 
<div class="uploadPics">  
    <div class="picCont" style="width:300px;height:300px;margin:20px auto 0;padding:0;" >  
        <div id=imgfield  style=overflow:hidden;width:100%;height:100% ></div>  
    </div>  
    <div class="picFooter">  
        <input type="file" accept=".jpg,.jpeg,.png,.gif" id="fileimg" name="fileimg" style="display:none" onchange="imgchange()" />  
        <span class="layui-btn layui-btn-sm"  onclick="getimg()">上传原图</span>  
        <!-- <span class="btn confirm" onclick="subform()">确认</span>   -->
    </div>  
  
</div> 
<div class="info">裁剪后图片:<br>图片大小:200 × 200</div>
<canvas id="myCan" width="200" height="200"></canvas>   
</div>  
  
</body>  

  
<script type="text/javascript">  
	//上传的文件名
	var fileName ="";
//	var nim = '';
    function subform() {  
  
        if($("#imgfield").html()){  
        	var ossurl = "";
            //获取裁剪完后的base64图片url,转换为blob  
        	var urlData=document.getElementById("myCan").toDataURL();  
        	var blob = dataURLtoBlob(urlData);  
            // blob转arrayBuffer
            var reader = new FileReader();
            reader.readAsArrayBuffer(blob);
            reader.onload = function (event) {
           	var opts = {
             		url : "web?module=stwmgr&action=Advertisement&method=getOSSSecurityToken&tokenId=<%=request.getParameter("tokenId")%>",
             		type : "POST",
             		processData : false,
             		contentType : false,
             		dataType : "json",
             		async:false,
             		success : function(token) {
             			var client = new OSS.Wrapper({
             						accessKeyId : token.accessKeyId,//key
             						accessKeySecret : token.accessKeySecret,//密码、
             						stsToken : token.securityToken,
             						region : token.ossRegion,//阿里云服务器地址
             						bucket : token.ossBucket,//上传的到的文件夹
             						secure:true
             					});
             			var key = "stw_mgr/images/portrait_images/" + getCurrentDate() + getExtension(fileName);
             			//arrayBuffer转buffer
             			var buffer = new OSS.Buffer(event.target.result);
             			//上传接口改为put
             			client.put(key, buffer).then(function(result) {
             				console.log(result);
          					var url = client.signatureUrl(key);
          					$("input[name='portraitUri']").val(key);
          					$("#portraitImage").attr("src", url);
             				console.log(url);
             				ossurl = url;
    					}).catch(function(err) {
    						console.log(err.message);
    					});
             		}
            };
            $.ajax(opts);
        }
       // uploadTitleImage(blob);          //网易云信上传
        nim.sendFile({
       	    scene: 'p2p',
       	    to: 'account',
       	    type: 'image',
       	 	blob: blob,
       	 //	wxFilePath: neteaseFile,
       	    beginupload: function(upload) {
       	        // - 如果开发者传入 fileInput, 在此回调之前不能修改 fileInput
       	        // - 在此回调之后可以取消图片上传, 此回调会接收一个参数 `upload`, 调用 `upload.abort();` 来取消文件上传
       	    },
       	    uploadprogress: function(obj) {
       	        console.log('文件总大小: ' + obj.total + 'bytes');
       	        console.log('已经上传的大小: ' + obj.loaded + 'bytes');
       	        console.log('上传进度: ' + obj.percentage);
       	        console.log('上传进度文本: ' + obj.percentageText);
       	    },
       	    uploaddone: function(error, file) {
       	        console.log(file);
       	        $('#neteaseUri').val(file.url);
       	        console.log('上传' + (!error?'成功':'失败'));
       	    }
       	});
        }  
    }  
  
  
    function getimg() {  
  
        $("#fileimg").click();  
  
    }  
    function imgchange() {  
  
        var localimg = $("#fileimg").get(0).files[0];  
  
        if(!localimg){  
            return;  
        }  
  
        fileName = localimg.name;  
        var fileSize = localimg.size;  
        var fileType=fileName.substring(fileName.lastIndexOf('.'),fileName.length).toLowerCase();  
        if(fileType!='.gif' && fileType!='.jpeg' && fileType!='.png' && fileType!='.jpg')  
        {  
            alert("上传失败,请上传jpg,jpeg,png格式的图片");  
            return;  
        }  
  
        var size=10*1024*1024;  
        if(fileSize>size){  
            alert("上传失败,请上传10MB以内的图片。");  
            return;  
        }  
  
        var reader=new FileReader();  
        //将文件读取为DataURL  
        reader.readAsDataURL(localimg);  
        reader.onload= function (e) {  
            var localimghtml = '<img id="cropbox" src="' +  e.target.result + '" >';  
            $("#imgfield").html(localimghtml);  
            initJcrop();  
        };  
  
    }  
  
  
    function initJcrop(){  
        $('#cropbox').Jcrop({  
            onSelect: updateCoords,  
            aspectRatio: 1,  
            boxWidth: 300,  
            boxHeight: 300  
        }, function () {  
  
            //图片实际尺寸  
            var bb = this.getBounds();  
            var bWidth= Number(bb[0]) / 2;  
            var bHeight= Number(bb[1]) / 2;  
  
            this.setSelect([0, 0, bWidth,bHeight]);  
  
  
            var ss = this.getWidgetSize();  
            var aheight = (300 - Number(ss[1])) / 2 + "px";  
            $(".jcrop-holder").css("margin-top", aheight);  
  
  
        });  
    }  
    function updateCoords(c){  
//      console.log(c);  
        var img=document.getElementById("cropbox");  
        var ctx=document.getElementById("myCan").getContext("2d");  
  
        //img,开始剪切的x,Y坐标宽高,放置图像的x,y坐标宽高。  
        ctx.drawImage(img,c.x,c.y, c.w, c.h,0,0,200,200);  
    }  
  
  
  
    //**dataURL to 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 });  
    }  
  
</script>  
  
  
</html> 
//点击头像框触发事件
$("#portraitImage").click(function(){
	 var c=document.getElementById("myCan");  
	 var cxt=c.getContext("2d");  
	 cxt.clearRect(0,0,c.width,c.height); 
	var porsrc = this.src;
	var orginimg = '<img id="cropbox" src="" crossorigin="Anonymous" >';  		//" crossorigin="Anonymous"
	//var image = new Image();
	//image.setAttribute("crossOrigin",'Anonymous')
	//image.crossOrigin = "Anonymous";
	//image.src = porsrc;
	$("#imgfield").html(orginimg);         //把原有的头像图片添加到可编辑框里
	$("#cropbox").attr("src",porsrc);
  //初始化插件方法
    initJcrop(); 
	layer.open({
		  type: 1,
		  scrollbar: false,
		  title: ['头像裁剪框', 'font-size:16px;'],
		  area: ['800px', '500px'],
		  btn: ['保存'],
		  tipsMore: true,
		  content: $("#showbg"),
		  yes: function(index, layero){
			  subform();
			  $('#showbg').css('display','none');
			  layer.closeAll();
		  },
		  cancel: function(){ 
			 $('#showbg').css('display','none');
		   }
		});
	});

最后想了一个改进的地方,就是之前已经有头像的用户,可能会复用以前的头像,所以点击修改的时候要把原来的图片带到图片处理框里。这里遇到了图片的跨越请求问题。解决办法是在img标签添加一个属性:crossorigin="Anonymous"。

前后大概5天的时间做了这么一个小小的功能,收获了图像处理的知识,虽然理解上并没有很深,但是能运用起来,也蛮有成就感的了。记录下探索的历程。望更进一步。

JCrop官网地址:http://deepliquid.com/content/Jcrop_Download.html

转载于:https://my.oschina.net/u/3476497/blog/1833713

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值