前言
cropper是一款使用简单且功能强大的图片剪裁jQuery插件。该图片剪裁插件支持图片放大缩小,支持图片旋转,支持触摸屏设备,支持canvas,并且支持跨浏览器使用。
cropper有两种方式上传截取的图片数据,一种是前端把裁剪的数据传到后台进行裁剪后保存,第二种是前端拿到剪裁后的数据,转成base64后上传,
后台通过二进制流上传图片信息。这里采用的是第二种方法。
1:需要引入cropper.js和cropper.css 官方下载地址 https://github.com/fengyuanchen/cropper
<link href="${BS}/css/cropper.min.css" rel="stylesheet">
<script src="${BS}/js/cropper.min.js">script>
2:注意要是传递图片的小大大于2m,可能会出现数据传递不到后台的情况,这个时候请修改tomcat 的server.xml配置,增加maxPostSize=“0”,因为tomcat设置默认的传递的数据大小不能大于2m
3:option相关参数说明:
container 容器 canvas 图片 crop 裁剪框
viewMode 显示模式
Type: Number
Default: 0
Options:
0: the crop box is just within the container 裁剪框只能在 1内移动
1: the crop box should be within the canvas 裁剪框 只能在 2图片内移动
2: the canvas should not be within the container 2图片 不全部铺满1 (即缩小时可以有一边出现空隙)
3: the container should be within the canvas 2图片 全部铺满1 (即 再怎么缩小也不会出现空隙)
dragMode 拖动模式
Default: 'crop'
Options:
'crop': create a new crop box 当鼠标 点击一处时根据这个点重新生成一个 裁剪框
'move': move the canvas 可以拖动图片
'none': do nothing 图片就不能拖动了
Define the dragging mode of the cropper.
toggleDragModeOnDblclick 默认true .是否允许 拖动模式 “crop” 跟“move” 的切换状态。。即当点下为crop 模式,如果未松开拖动这时就是“move”模式。放开后又为“crop”模式
preview 截图的显示位置 型:String(jQuery选择器),默认值''
responsive :类型:Boolean,默认值true。是否在窗口尺寸改变的时候重置cropper。
checkImageOrigin:类型:Boolean,默认值true。默认情况下,插件会检测图片的源,如果是跨域图片,图片元素会被添加crossOrigin class,并会为图片的url添加一个时间戳来使getCroppedCanvas变为可用。添加时间戳会使图片重新加载,以使跨域图片能够使用getCroppedCanvas。在图片上添加crossOrigin class会阻止在图片url上添加时间戳,及图片的重新加载。
background:类型:Boolean,默认值true。是否在容器上显示网格背景。 要想改背景,我是直接改,cropper.css样式中的 cropper-bg
canvas(图片)相关
movable:类型:Boolean,默认值true。是否允许移动图片
rotatable:类型:Boolean,默认值true。是否允许旋转图片。
scalable 默认 true 。 是否允许扩展图片。(暂时不知道干嘛用)
zoomable 默认true, 石头允许缩放图片。
zoomOnWheel 默认 true 是否允许鼠标滚轴 缩放图片
zoomOnTouch 默认true 是否允许触摸缩放图片(触摸屏上两手指操作。)
wheelZoomRatio 默认0.1 师表滚轴缩放图片比例。即滚一下。图片缩放多少。如 0.1 就是图片的10%
crop(裁剪框)相关
aspectRatio 裁剪框比例 默认NaN 例如:: 1 / 1,//裁剪框比例 1:1
modal:类型:Boolean,默认值true。是否在剪裁框上显示黑色的模态窗口。
cropBoxMovable :默认true ,是否允许拖动裁剪框
cropBoxResizable :默认 true,//是否允许拖动 改变裁剪框大小
autoCrop:类型:Boolean,默认值true。是否允许在初始化时自动出现裁剪框。
autoCropArea:类型:Number,默认值0.8(图片的80%)。0-1之间的数值,定义自动剪裁框的大小。
highlight:类型:Boolean,默认值true。是否在剪裁框上显示白色的模态窗口。
guides:类型:Boolean,默认值true。是否在剪裁框上显示虚线。
center: 默认true 是否显示裁剪框 中间的+
restore : 类型:Boolean,默认值true 是否调整窗口大小后恢复裁剪区域。
大小相关
minContainerWidth:类型:Number,默认值200。容器的最小宽度。
minContainerHeight:类型:Number,默认值100。容器的最小高度。
minCanvasWidth:类型:Number,默认值0。canvas 的最小宽度(image wrapper)。
minCanvasHeight:类型:Number,默认值0。canvas 的最小高度(image wrapper)。
监听触发的方法
build:类型:Function,默认值null。build.cropper事件的简写方式。 ====== 。控件初始化前执行
built:类型:Function,默认值null。built.cropper事件的简写方式。 ====== 空间初始化完成后执行
dragstart:类型:Function,默认值null。dragstart.cropper事件的简写方式。 ====== 拖动开始执行
dragmove:类型:Function,默认值null。dragmove.cropper事件的简写方式。====== 拖动移动中执行
dragend:类型:Function,默认值null。dragend.cropper事件的简写方式。====== 拖动结束执行
zoomin:类型:Function,默认值null。zoomin.cropper事件的简写方式。 ====== 缩小执行
zoomout:类型:Function,默认值null。zoomout.cropper事件的简写方式。 ====== 放大执行
4:demo 下载地址 http://download.csdn.net/download/qq_15988615/10120181
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<c:set var="BS" value="${pageContext.request.contextPath}">c:set>
<html>
<head>
<title>cropper图片裁剪案例title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="baidu-tc-cerfication" content="315f7ed10c0de83badbd33934a33aec1">
<meta name="viewport" content=">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta content="telephOne=no,email=no" name="format-detection">
head>
<link rel="stylesheet" href="${BS}/css/swiper.min.css" media="screen" charset="utf-8">
<link rel="stylesheet" href="${BS}/css/edit-image.css" media="screen" charset="utf-8">
<link href="${BS}/css/cropper.min.css" rel="stylesheet">
<input type="hidden" id="BS_s" value="${BS}">
<body class="page-address-book ">
<div onclick="Javascript:$('#inputImage').click();" style="height:70%;">
<img title="点击更换背景图片" class="logo left" style="top:12%;left:42%;width:100%;height:100%" src="${BS}/images/6.jpg">
div>
<input style="display: none;" id="inputImage" name="file" type="file" accept="image/*">
点击上面背景图片更换图片
<div id="showEdit" class="containerImage Hide cliper_wrapper">
<img id="EditImg" src="">
<div class="footer-btn" style="height: 55px;">
<button type="button" style="width: 130px;font-size: 20px;height: 40px;margin-top: 8px;" class="ReselectPhoto" onclick="Javascript:$('#inputImage').click();">重选照片button>
<button id="cut" type="button" style="width: 100px;font-size: 20px;height: 40px;margin-top: 8px;background-color: #3A9E9E;border: 1px solid #3A9E9E;" class="Cut">剪切button>
<button id="submit" type="button" style="width: 100px;font-size: 20px;height: 40px;margin-top: 8px;" class="Cut">提交button>
div>
div>
<script src="${BS}/js/jquery.min.js">script>
<script src="${BS}/js/cropper.min.js">script>
body>
html>
js部分
<script> $(function () { 'use strict';//表示强规则 var Cropper = window.Cropper; var cOnsole= window.console || { log: function () {} }; var URL = window.URL || window.webkitURL; var $image = $('#EditImg'); //获取图片截取的位置 var screenWidth = $(window).width(); var screenHeight = $(window).height(); var $dataX = $('#dataX'); var $dataY = $('#dataY'); var $dataHeight = $('#dataHeight'); var $dataWidth = $('#dataWidth'); var $dataRotate = $('#dataRotate'); var $dataScaleX = $('#dataScaleX'); var $dataScaleY = $('#dataScaleY'); var optiOns= { containerHeight : screenWidth, containerWidth : screenHeight, guides :true,//裁剪框虚线 默认true有 aspectRatio: 1 / 1, //裁剪框比例1:1 responsive : true,// 是否在窗口尺寸改变的时候重置cropper background : true,// 容器是否显示网格背景 zoomable : true,//是否允许放大缩小图片 movable : false,//是否允许移动剪裁框 resizable : false,//是否允许改变剪裁框的大小 cropBoxMovable :false,//是否允许拖动裁剪框 cropBoxResizable :false,//是否允许拖动 改变裁剪框大小 crop: function (e) { $dataX.val(Math.round(e.x)); $dataY.val(Math.round(e.y)); $dataHeight.val(Math.round(e.height)); $dataWidth.val(Math.round(e.width)); $dataRotate.val(e.rotate); $dataScaleX.val(e.scaleX); $dataScaleY.val(e.scaleY); } }; $('#EditImg').cropper(options); // Options var originalImageURL = $image.attr('src'); var uploadedImageURL; var $inputImage = $('#inputImage'); URL = window.URL || window.webkitURL; var blobURL; if (URL) { $inputImage.change(function () { var files = this.files, file; if (files && files.length) { file = files[0]; if (/^image\/\w+$/.test(file.type)) { blobURL = URL.createObjectURL(file); $image.one('built.cropper', function () { URL.revokeObjectURL(blobURL); // Revoke when load complete }).cropper('reset', true).cropper('replace', blobURL); //$inputImage.val(''); $("#showEdit").removeClass('Hide'); } else { //alert('Please choose an image file.'); } } }); } else { $inputImage.parent().remove(); } //裁剪图片 $("#cut").on("click", function () { var dataURL = $image.cropper("getCroppedCanvas"); var imgurl = dataURL.toDataURL("image/*", 0.5); $image.cropper('destroy').attr('src', imgurl).cropper(options); }); //提交图片 $("#submit").on("click", function () { var accessory = $('#inputImage').val(); if (typeof accessory == "null"){ alert("is null"); return ; } var accessoryName = accessory.substring(accessory.lastIndexOf("\\")+1,accessory.length);//截取原文件名 var dataURL = $image.cropper("getCroppedCanvas");//拿到剪裁后的数据 var data = dataURL.toDataURL("image/*", 0.5);//转成base64 if (typeof data == "null"){ alert("is null"); return ; } var BS_s = $("#BS_s").val(); $.ajax({ url: BS_s+"/wxFirst/uploadImgBase", dataType:'json', type: "POST", data: { fileName : accessoryName, imgBase64 : data.toString() }, timeout : 10000, //超时时间设置,单位毫秒 async: true, success: function (result) { }, error: function (returndata) { } }); }); }); script>
后台部分
/** * 上传图片 * @param id * @return */
@RequestMapping("/uploadImgBase")
@ResponseBody
public Map uploadImgBase(@RequestParam(value="imgBase64",defaultValue="") String imgBase64,@RequestParam(value="fileName",defaultValue="") String fileName,HttpServletRequest request,HttpServletResponse response){
String TrueDirectory = "ImgFiles"+File.separator+"backgroundImg";
String inventedDirectory = "ImgFiles/"+"backgroundImg";
String directory = TrueDirectory+"-"+inventedDirectory;
Map map = ImageUtil.uploadImgBase64(request,imgBase64, directory, fileName);
return map;
}
/** * 上传base64 单个图片工具类 * @param imgBase64 图片base64 * @param fileName 图片名称 * @return */
public static Map uploadImgBase64(HttpServletRequest request,String imgBase64,String Directory,String oldFileName){
Map uploadImageMap = new HashMap();
String oldFileName2 = oldFileName.substring(0,oldFileName.lastIndexOf("."));
String lastFileName = oldFileName.substring(oldFileName.lastIndexOf("."),oldFileName.length());
String fileName = oldFileName2+System.currentTimeMillis()+lastFileName;// 重命名上传后的文件名
uploadImageMap.put("oldFileName", oldFileName);
//上传本地tomcat路径
String path = request.getSession().getServletContext().getRealPath("/") + Directory.split("-")[0] + File.separator+ fileName;
String filePath = request.getSession().getServletContext().getRealPath("/") + Directory.split("-")[0];
//上传服务器路径
String phoUrl = "/" + Directory.split("-")[1]+"/" + fileName;
String header ="data:image";
String[] imageArr=imgBase64.split(",");
if(imageArr[0].contains(header)){//是img的
// 去掉头部
imgBase64=imageArr[1];
//image = image.substring(header.length());
// 写入磁盘
BASE64Decoder decoder = new BASE64Decoder();
try{
byte[] decodedBytes = decoder.decodeBuffer(imgBase64); //将字符串格式的image转为二进制流(biye[])的decodedBytes
File targetFile = new File(filePath);
if(!targetFile.exists()){
targetFile.mkdirs();
}
FileOutputStream out = new FileOutputStream(path); //新建一个文件输出器,并为它指定输出位置imgFilePath
out.write(decodedBytes); //利用文件输出器将二进制格式decodedBytes输出
out.flush();
out.close(); //关闭文件输出器
uploadImageMap.put("success", "上传文件成功!");
uploadImageMap.put("path", path);
uploadImageMap.put("phoUrl", phoUrl);
return uploadImageMap;
}catch(Exception e){
uploadImageMap.put("err", "上传文件失败!");
return uploadImageMap;
}
}else{
uploadImageMap.put("err", "上传文件失败!");
return uploadImageMap;
}
}
效果图