JavaScript实现本地图片上传前进行裁剪预览
本项目支持IE8+,测试环境IE8,IE9,IE10,IE11,Chrome,FireFox测试通过
另:本项目并不支持Vue,React等,也不建议,引入JQuery和Vue、React本身提倡的开发方式并不一致
注:本项目未对移动端进行测试,不保证移动端可以使用,并且也不推荐移动端使用这个项目,移动端建议使用Cropper插件,功能更丰富,也更强大,使用更便捷,地址:https://github.com/fengyuanchen/cropper
在工作中会有很多项目需要实现图片上传裁剪预览的功能,但目前很多插件基本上在较低版本的浏览器上使用的是flash来实现,我则更倾向于尽量使用js来解决,在js无能为力的时候再借助其他的工具(其实更多的还是因为不会,又懒得去学╮(╯﹏╰)╭,毕竟flash已经可以说是被淘汰了),当然,实现这些功能的插件也不少,只不过,基本上都没有实现页面无刷新上传的功能,或者都是需要先上传图片再对已上传的图片进行裁剪,或者两个问题都有,这就不是我想要的功能了,我希望的是能够在还未上传的时候就对其进行预览,并裁剪,,也就是实现本地预览裁剪并上传裁剪结果。那么,废话收了那么多,动手呗!
此项目中使用的裁剪数据采集插件是Jcrop插件,这个插件感觉做的还是挺好的,那么下一步就是进一步封装这个插件咯,也就是说,需要自己来实现预览和上传,这个最终能够支持到IE8+
先来上个效果图先
左侧大图就是我们要上传并进行裁剪的原图,而右侧则是最终裁剪的结果,恩,看起来好像还是可以的,恩,好,继续
html结构很简单,无非就是引入css,js,写个div就够了,来看下html结构先(样式直接写在了页面上,并没有进行分离,懒-_-|||)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>IE Image Upload</title>
<link rel="stylesheet" href="css/jquery.Jcrop.min.css">
<script src="js/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="js/jquery.Jcrop.min.js"></script>
<script type="text/javascript" src="js/imgCropUpload.js"></script>
<style type="text/css">
body {
font-size: 16px;
font-family:"Microsoft YaHei",Arial, Helvetica, sans-serif
}
*,
*:before,
*:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
} .crop-picker-wrap {
position: relative;
width: 100px;
height: 30px;
overflow: hidden;
}
.crop-picker {
width: %;
height: %;
line-height: ; -webkit-appearance: none;
margin: ;
border: none;
border-radius: 5px;
padding: 9px ;
background-color: #1ab2ff; color: #fff;
cursor: pointer;
}
.crop-picker-file {
position: absolute;
top: ;
right: ;
height: %;
opacity: ;
cursor: pointer;
filter: alpha(opacity=);
} .crop-wrapper {
display: inline-block;
min-width: 750px;
margin: 10px ;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 5px 2px #ccc;
} .crop-container {
font-size: ;
} .crop-container img[src=""] {
visibility: hidden;
} .crop-area-wrapper,
.crop-preview-wrapper {
display: inline-block;
vertical-align: top;
}
.crop-area-wrapper {
width: 500px;
height: 400px;
}
.crop-preview-wrapper {
width: 200px;
height: 200px;
margin-left: 28px;
overflow: hidden;
}
.crop-preview-container {
position: relative;
overflow: hidden;
}
.crop-operate {
text-align: center;
margin: 10px ;
}
.crop-save,
.crop-cancel {
display: inline-block;
vertical-align: middle; width: 150px;
height: 50px;
line-height: 50px; -webkit-appearance: none;
margin: 5px;
border: none;
border-radius: 5px;
background-color: #1ab2ff; color: #fff;
cursor: pointer;
}
.crop-hidden {
display: none;
}
</style>
</head>
<body>
<div id="TCrop"></div>
<script type="text/javascript">
$(function() {
Crop.init({
id: 'TCrop',
/* 上传路径 */
url: '',
/* 允许上传的图片的后缀 */
allowsuf: ['jpg', 'jpeg', 'png', 'gif'],
/* JCrop参数设置 */
cropParam: {
minSize: [, ], // 选框最小尺寸
maxSize: [, ], // 选框最大尺寸
allowSelect: true, // 允许新选框
allowMove: true, // 允许选框移动
allowResize: true, // 允许选框缩放
dragEdges: true, // 允许拖动边框
onChange: function(c) {}, // 选框改变时的事件,参数c={x, y, x1, y1, w, h}
onSelect: function(c) {} // 选框选定时的事件,参数c={x, y, x1, y1, w, h}
},
/* 是否进行裁剪,不裁剪则按原图上传,默认进行裁剪 */
isCrop: true,
/* 图片上传完成之后的回调,无论是否成功上传 */
onComplete: function(data) {
console.log('upload complete!');
}
});
});
</script>
</body>
</html>
接下来我们来看看js的实现
首先我们来分析下流程
简单点说就是:选图片 -> 预览 -> 裁剪 -> 上传,就像下面这样
详细点:选择文件 -> 判断文件类型是否允许上传 -> 判断浏览器类型 -> 预览图片 -> 裁剪并实时更新裁剪结果图 -> 上传原图及裁剪信息,就像下面这样
注意:这里有一点需要关注下,那就是,有些同学可能会发现在运行我这个项目的时候,那个隐藏的input文件选择按钮并没有被真正的隐藏起来,而是定位到了选择图片那个标签上,为什么要这么做呢?而不直接使用js来出发input的click事件?原因在于,为了兼容IE8!在IE8下,使用js触发的input文件选择按钮,并不能进行提交,会出现拒绝访问的错误,这是IE8的一个安全策略,必须是用户手动触发的input选择的文件才可以在form表单中被提交
本地图片预览
对于这个项目而言,最重要的就是在不同的浏览器里面如何进行预览,至于裁剪,则全部交由Jcrop插件来进行,那么我们就来看看如何实现预览吧
对于支持HTML5的File接口的浏览器
对于支持的浏览器,则可以直接使用FileReader获取图片的数据,并在页面进行展示,js如下:
var img = document.createElement('img');
img.style.visibility = 'hidden';
cropArea.appendChild(img); img.onload = function() {
/* 在图片加载完成之后便可以获取原图的大小,根据原图大小和预览区域大小获取图片的缩放比例以及原图在预览时所展现的大小 */
var scaleOpt = _getScale(cropArea.clientWidth, cropArea.clientHeight, img.offsetWidth, img.offsetHeight);
img.setAttribute('style', 'position: absolute;visibility: visible;width: ' + scaleOpt.w + 'px;height: ' + scaleOpt.h + 'px'); if(!opt.isCrop) {return ;} var cropPreviewImg = img.cloneNode(true);
cropPreview.appendChild(cropPreviewImg); _startCrop(img, jcropOpt); /* 记录原始比例,上传数据需要还原实际裁剪尺寸 */
Crop.ratio = scaleOpt.scale;
/* 记录裁剪图片及裁剪预览图像对象,更新预览图时需要使用 */
Crop.cropPreview = {
cropAreaImg: img,
cropPreviewImg: cropPreviewImg
};
};
var fr = new FileReader();
fr.onload = function(eve) {
img.src = eve.target.result;
}
fr.readAsDataURL(fileInp.files[]);
对于不支持HTML5的File接口的浏览器
对于不支持的IE8、9浏览器,则必须要使用滤镜来进行实现,js实现如下,
PS:至于不考虑其他不支持的浏览器,原因在于,现在浏览器除IE8、9是被绑定在windows上并且基本不会自动升级外,其余现代浏览器都已实现了File接口,故不去考虑
var img = document.createElement('div');
img.style.visibility = 'hidden';
img.style.width = '100%';
img.style.height = '100%';
cropArea.appendChild(img); fileInp.select();
var src = document.selection.createRange().text;
// console.log(document.selection.createRange()); var img_filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src='" + src + "')";
img.style.filter = img_filter; /* 需等待滤镜加载完毕之后才能进行下一步操作 */
window.setTimeout(function() {
_loadFiter(cropArea, img);
}, ); /* 加载滤镜,等待两秒,超时则判定加载失败 */
function _loadFiter(cropArea, img) {
var time = ;
if(img.offsetWidth != cropArea.clientWidth) {
/* 滤镜加载成功,进入裁剪流程 */
_filterCrop(cropArea, img);
} else {
time ++;
if(time < ) {
window.setTimeout(function() {
_loadFiter(cropArea, img);
}, );
} else {
alert('图片加载失败,请重试!');
}
}
}; /* 使用滤镜的裁剪 */
function _filterCrop(cropArea, img) {
var scaleOpt = _getScale(cropArea.clientWidth, cropArea.clientHeight, img.offsetWidth, img.offsetHeight);
/* 更改滤镜设置 */
var s_filter = img.style.filter.replace(/sizingMethod='image'/g, "sizingMethod='scale'");
var jcropOpt = _getOpt().cropParam; img.setAttribute('style', 'position: absolute;visibility: visible;width: ' + scaleOpt.w + 'px;height: ' + scaleOpt.h + 'px;filter: ' + s_filter); if(!_getOpt().isCrop) {return ;} var cropPreview = cropArea.nextSibling.firstChild;
var cropPreviewImg = img.cloneNode(true);
cropPreview.appendChild(cropPreviewImg); _startCrop(img, jcropOpt); /* 记录原始比例,上传数据需要还原实际裁剪尺寸 */
Crop.ratio = scaleOpt.scale;
/* 记录裁剪图片及裁剪预览图像对象,更新预览图时需要使用 */
Crop.cropPreview = {
cropAreaImg: img,
cropPreviewImg: cropPreviewImg
};
};
以上便可以实现本地预览,以下放出所有封装后的源码
如果有同学需要使用这个项目的话,可以直接将以下代码封装copy,并保存为imgCropUpload.js,再如上面那个HTML页面那样引入即可
;(function(global, $, Crop) {
var defaultOpt = {
/* 整个图片选择、裁剪、上传区域的最外围包裹元素id,默认TCrop */
id: 'TCrop',
/* 上传路径 */
url: '',
/* 允许上传的图片的后缀,暂时支持以下四种,其余格式图片未测试 */
allowsuf: ['jpg', 'jpeg', 'png', 'gif'],
/* JCrop参数设置 */
cropParam: {
minSize: [, ], // 选框最小尺寸
maxSize: [, ], // 选框最大尺寸
allowSelect: true, // 允许新选框
allowMove: true, // 允许选框移动
allowResize: true, // 允许选框缩放
dragEdges: true, // 允许拖动边框
onChange: function(c) {}, // 选框改变时的事件
onSelect: function(c) {} // 选框选定时的事件,参数c={x, y, x1, y1, w, h}
},
/* 是否进行裁剪,不裁剪则按原图上传,默认进行裁剪 */
isCrop: true,
/* 图片上传完成之后的回调,无论是否成功上传 */
onComplete: function(data) {
console.log('upload complete!');
}
}; /* 记录jcrop实例 */
var jcropApi; /* 创建Dom结构 */
/* 完整DOM结构 --s-- */
/*
<iframe id="uploadIfr" name="uploadIfr" class="crop-upload-ifr"></iframe>
<form action="index.html" enctype="multipart/form-data" method="post" target="uploadIfr">
<input type="hidden" name="cropData">
<div class="crop-picker-wrap">
<button class="crop-picker" type="button">选择图片</button>
<input type="file" id="file" class="crop-picker-file">
</div>
<div class="crop-wrapper">
<div class="crop-container clearfix">
<div class="crop-area-wrapper"><img src="" alt=""></div>
<div class="crop-preview-wrapper"><img src="" alt=""></div>
</div>
<div class="crop-operate">
<div class="crop-save">上传原图</div>
<div class="crop-save">保存截图</div>
<div class="crop-cancel">取消</div>
</div>
</div>
</form>
*/
/* 完整DOM结构 --e-- */
function _createDom($wrap, opt) {
var accept = 'image/' + opt.allowsuf.join(', image/');
var $ifr = $('<iframe id="uploadIfr" name="uploadIfr" class="crop-hidden"></iframe>');
var $form = $('<form action="' + opt.url + '" enctype="multipart/form-data" method="post" target="uploadIfr"/>');
var $cropDataInp = $('<input type="hidden" name="cropData">');
var $picker = $('<div class="crop-picker-wrap"><button class="crop-picker" type="button">选择图片</button></div>');
var $fileInp = $('<input type="file" id="file" accept="' + accept + '" class="crop-picker-file">');
$picker.append($fileInp);
$form.append($cropDataInp).append($picker); var $cropWrap = $('<div class="crop-wrapper crop-hidden"/>');
var $cropArea = $('<div class="crop-area-wrapper"></div>');
var $cropPreviewWrap = $('<div class="crop-preview-wrapper"></div>');
var $cropPreview = $('<div class="crop-preview-container"/>');
$cropPreviewWrap.append($cropPreview);
var $cropContainer = $('<div class="crop-container"/>').append($cropArea).append($cropPreviewWrap);
$cropWrap.append($cropContainer);
// var $saveSource = $('<div class="crop-save">上传原图</div>');
var $save = $('<div class="crop-save">保存</div>');
var $cropCancel = $('<div class="crop-cancel">取消</div>');
var $cropOpe = $('<div class="crop-operate"/>').append($save).append($cropCancel); if(!opt.isCrop) {
$cropPreviewWrap.addClass('crop-hidden');
} $cropWrap.append($cropOpe);
$form.append($cropWrap); $wrap.append($ifr).append($form); return {
$ifr: $ifr,
$form: $form,
$cropDataInp: $cropDataInp,
$cropPicker: $picker,
$fileInp: $fileInp,
$cropWrap: $cropWrap,
$cropArea: $cropArea,
$cropPreview: $cropPreview,
// $saveSource: $saveSource,
$save: $save,
$cancel: $cropCancel
};
}; /*
* 绑定事件
*
*/
function _bind($cropObj, opt) { var $cropPicker = $cropObj.$cropPicker;
var $fileInp = $cropObj.$fileInp;
var $save = $cropObj.$save;
var $cancel = $cropObj.$cancel;
var $ifr = $cropObj.$ifr; $fileInp.change(function(eve) {
if(!this.value) {return ;}
var fileSuf = this.value.substring(this.value.lastIndexOf('.') + );
if(!_checkSuf(fileSuf, opt.allowsuf)) {
alert('只允许上传后缀名为' + opt.allowsuf.join(',') + '的图片');
return ;
}
/* 进入裁剪流程 */
_crop($cropObj, this);
$cropPicker.addClass('crop-hidden').next().removeClass('crop-hidden');
}); $save.click(function(eve) {
eve.preventDefault();
Crop.upload();
}); $cancel.click(function(eve) {
eve.preventDefault();
Crop.cancel();
}); /* iframe的load应该延迟绑定,避免首次插入文档中加载完毕时触发load事件 */
window.setTimeout(function() {
$ifr.load(function() {
var body = this.contentWindow.document.body;
var text = body.innerText;
opt.onComplete(text);
});
}, );
}; /* 检查文件是否符合上传条件 */
function _checkSuf(fileSuf, suffixs) {
for(var i = , j = suffixs.length;i < j; i ++) {
if(fileSuf.toLowerCase() == suffixs[i].toLowerCase()) {
return true;
}
}
return false;
}; /* 主要裁剪流程 */
function _crop($cropObj, fileInp) {
var cropArea = $cropObj.$cropArea.get();
var cropPreview = $cropObj.$cropPreview.get();
var opt = _getOpt();
var jcropOpt = opt.cropParam;
cropArea.innerHTML = '';
if(fileInp.files && fileInp.files[]) {
var img = document.createElement('img');
img.style.visibility = 'hidden';
cropArea.appendChild(img); img.onload = function() {
/* 在图片加载完成之后便可以获取原图的大小,根据原图大小和预览区域大小获取图片的缩放比例以及原图在预览时所展现的大小 */
var scaleOpt = _getScale(cropArea.clientWidth, cropArea.clientHeight, img.offsetWidth, img.offsetHeight);
img.setAttribute('style', 'position: absolute;visibility: visible;width: ' + scaleOpt.w + 'px;height: ' + scaleOpt.h + 'px'); if(!opt.isCrop) {return ;} var cropPreviewImg = img.cloneNode(true);
cropPreview.appendChild(cropPreviewImg); _startCrop(img, jcropOpt); /* 记录原始比例,上传数据需要还原实际裁剪尺寸 */
Crop.ratio = scaleOpt.scale;
/* 记录裁剪图片及裁剪预览图像对象,更新预览图时需要使用 */
Crop.cropPreview = {
cropAreaImg: img,
cropPreviewImg: cropPreviewImg
};
};
var fr = new FileReader();
fr.onload = function(eve) {
img.src = eve.target.result;
}
fr.readAsDataURL(fileInp.files[]);
} else {
var img = document.createElement('div');
img.style.visibility = 'hidden';
img.style.width = '100%';
img.style.height = '100%';
cropArea.appendChild(img); fileInp.select();
var src = document.selection.createRange().text;
// console.log(document.selection.createRange()); var img_filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src='" + src + "')";
img.style.filter = img_filter; /* 需等待滤镜加载完毕之后才能进行下一步操作 */
window.setTimeout(function() {
_loadFiter(cropArea, img);
}, );
}
}; /* 加载滤镜,等待两秒,超时则判定加载失败 */
function _loadFiter(cropArea, img) {
var time = ;
if(img.offsetWidth != cropArea.clientWidth) {
/* 滤镜加载成功,进入裁剪流程 */
_filterCrop(cropArea, img);
} else {
time ++;
if(time < ) {
window.setTimeout(function() {
_loadFiter(cropArea, img);
}, );
} else {
alert('图片加载失败,请重试!');
}
}
}; /* 使用滤镜的裁剪 */
function _filterCrop(cropArea, img) {
var scaleOpt = _getScale(cropArea.clientWidth, cropArea.clientHeight, img.offsetWidth, img.offsetHeight);
/* 更改滤镜设置 */
var s_filter = img.style.filter.replace(/sizingMethod='image'/g, "sizingMethod='scale'");
var jcropOpt = _getOpt().cropParam; img.setAttribute('style', 'position: absolute;visibility: visible;width: ' + scaleOpt.w + 'px;height: ' + scaleOpt.h + 'px;filter: ' + s_filter); if(!_getOpt().isCrop) {return ;} var cropPreview = cropArea.nextSibling.firstChild;
var cropPreviewImg = img.cloneNode(true);
cropPreview.appendChild(cropPreviewImg); _startCrop(img, jcropOpt); /* 记录原始比例,上传数据需要还原实际裁剪尺寸 */
Crop.ratio = scaleOpt.scale;
/* 记录裁剪图片及裁剪预览图像对象,更新预览图时需要使用 */
Crop.cropPreview = {
cropAreaImg: img,
cropPreviewImg: cropPreviewImg
};
}; /* 开始裁剪,初始化裁剪插件 */
function _startCrop(img, jcropOpt) {
var imgW = img.offsetWidth;
var imgH = img.offsetHeight;
var minW = jcropOpt.minSize[], minH = jcropOpt.minSize[];
var offsetWidth = (imgW / ) - (minW / );
var offsetHeight = (imgH / ) - (minH / );
var obj = {
x: offsetWidth,
y: offsetHeight,
x2: offsetWidth + minW,
y2: offsetHeight + minH,
w: minW,
h: minH
};
$(img).Jcrop(jcropOpt, function() {
jcropApi = this;
this.animateTo([obj.x, obj.y, obj.x2, obj.y2]);
});
}; /* 获取配置参数opt */
function _getOpt() {
var id = Crop.crop.id;
var cropDom = document.getElementById(id);
var opt = $.data(cropDom, 'crop').opt;
return opt;
}; /*
* 获取缩放比例
*
* 原始宽高vw,vh
* 实际显示宽高sw,sh
* 返回:
* {w,h,scale:max(sw/vw,sh/vh)}
* w,h均为缩放到sw、sh后的宽高
*/
function _getScale(vw, vh, sw, sh) {
vw = Number(vw);
vh = Number(vh);
sw = Number(sw);
sh = Number(sh);
if(vw <= || vh <= ) {
console.log('参数不能为0');
return false;
}
var wScale = sw / vw;
var hScale = sh / vh;
var scale = , w, h; if(wScale > hScale) {
scale = wScale;
w = vw;
h = sh / scale;
} else {
scale = hScale;
h = vh;
w = sw / scale;
} return {
scale: scale,
w: w,
h: h
};
}; /* 更新裁剪预览图 */
function _updatePreview(c) {
var cropAreaImg = Crop.cropPreview.cropAreaImg;
var cropPreviewImg = Crop.cropPreview.cropPreviewImg;
var $cropObj = $.data(document.getElementById(Crop.crop.id), 'crop').$cropObj;
var $cropDataInp = $cropObj.$cropDataInp;
var $cropPreview = $cropObj.$cropPreview;
var $previewParent = $cropPreview.parent();
var vw = $previewParent.width(), vh = $previewParent.height();
var scaleOpt = _getScale(vw, vh, c.w, c.h);
$cropPreview.width(scaleOpt.w);
$cropPreview.height(scaleOpt.h);
var width = $(cropAreaImg).width() / scaleOpt.scale;
var height = $(cropAreaImg).height() / scaleOpt.scale;
var top = -(c.y / scaleOpt.scale);
var left = -(c.x / scaleOpt.scale);
cropPreviewImg.style.width = width + 'px';
cropPreviewImg.style.height = height + 'px';
cropPreviewImg.style.top = top + 'px';
cropPreviewImg.style.left = left + 'px';
_setCropData($cropDataInp, c);
}; /* 设置裁剪数据 */
function _setCropData($cropDataInp, c) {
var ratio = Crop.ratio;
var data = {
x: c.x * ratio,
y: c.y * ratio,
w: c.w * ratio,
h: c.h * ratio
}; var dataJson = JSON.stringify(data);
$cropDataInp.val(dataJson);
}; /* 扩展配置参数,尤其是Jcrop裁剪参数中的onSelect,onChange参数 */
function _extendOpt(opt) {
opt = $.extend(true, {}, defaultOpt, opt);
var select = opt.cropParam.onSelect;
var change = opt.cropParam.onChange;
if(Object.prototype.toString.call(select) == '[object Function]') {
opt.cropParam.onSelect = function(c) {
_updatePreview.call(jcropApi, c);
select.call(jcropApi, c);
};
} else {
opt.cropParam.onSelect = _updatePreview;
}
if(Object.prototype.toString.call(change) == '[object Function]') {
opt.cropParam.onChange = function(c) {
_updatePreview.call(jcropApi, c);
change.call(jcropApi, c);
}
} else {
opt.cropParam.onChange = _updatePreview;
}
return opt;
}; /* 初始化上传裁剪区域 */
function init(opt) {
var opt = _extendOpt(opt);
var $uploadCropWrap = $('#' + opt.id);
var hasDom = true;
if($uploadCropWrap.length == ) {
$uploadCropWrap = $('<div id="' + opt.id + '" />');
hasDom = false;
} /* 清空Dom原有内部结构 */
$uploadCropWrap.html('');
var $cropObj = _createDom($uploadCropWrap, opt); $.data($uploadCropWrap.get(), 'crop', {opt: opt, $cropObj: $cropObj});
hasDom || $('body').append($uploadCropWrap); _bind($cropObj, opt); Crop.crop = {id: opt.id, hasDom: hasDom};
}; /* 上传 */
function upload() {
var id = (Crop.crop && Crop.crop.id) || '';
var dom = document.getElementById(id);
if(!dom) {
return ;
}
var form = $.data(dom, 'crop').$cropObj.$form.get();
form.submit();
}; /* 取消裁剪 */
function cancel() {
var id = (Crop.crop && Crop.crop.id) || "";
var dom = document.getElementById(id);
if(!dom) {
return ;
}
var $cropObj = $.data(dom, 'crop').$cropObj;
$cropObj.$cropWrap.addClass('crop-hidden');
$cropObj.$cropPicker.removeClass('crop-hidden');
}; /* 销毁上传裁剪区域 */
function destroy() {
var crop = Crop.crop || {};
var $cropWrap = $('#' + crop.id);
if(crop.hasDom === true) {
$cropWrap.html('');
} else {
$cropWrap.remove();
}
}; if($.isEmptyObject(Crop)) {
global.Crop = Crop = {
init: init,
upload: upload,
cancel: cancel,
destroy: destroy,
crop: {}
};
} else {
Crop = $.extend(Crop, {
init: init,
upload: upload,
cancel: cancel,
destroy: destroy,
crop: {}
});
}
})(window, jQuery, window.Crop || {});
后台接受到的数据将会是两个,1、上传的图片的二进制文件,2、json格式的裁剪数据,例如:'{"x":366.592,"y":208.89600000000002,"w":389.12,"h":335.872}'
由于后端代码属于工作上的业务代码,这里不再放出,其实实现也很简单,也没什么复杂的逻辑,只需要对接收到的图片直接进行裁剪即可,因为传给后端的裁剪数据就是根据原图的大小进行裁剪的数据
恩,以上,便是我个人在工作中遇到的关于本地图片上传预览裁剪遇到的问题,并将之整理实现,我知道还有很多不足,我会继续努力的。
各位如若发现什么问题,也可以指出,一起探讨进步,谢谢!
JavaScript实现本地图片上传前进行裁剪预览的更多相关文章
- JavaScript实现本地图片上传预览功能(兼容IE、chrome、FF)
需要解决的问题有:本地图片如何在上传前预览.编辑:最近发现这个功能很多是基于flash实现的,很多JavaScript实现的代码兼容性都很差,特别是在IE和firefox和chrome三个浏览器上不兼 ...
- html + js 实现图片上传,压缩,预览及图片压缩后得到Blob对象继续上传问题
先上效果 上传图片后(设置了最多上传3张图片,三张后上传按钮消失) 点击图片放大,可以使用删除和旋转按钮 (旋转功能主要是因为ios手机拍照后上传会有写图片被自动旋转,通过旋转功能可以调正) html ...
- TinyMCE的使用(包括汉化及本地图片上传功能)
TinyMCE我就不多介绍了,这是下载地址:https://www.tinymce.com/download/ 下载下来是英文版,要汉化也很简单.首先去网上随便下载个汉化包,然后把汉化包解压后的lan ...
- html之file标签 --- 图片上传前预览 -- FileReader
记得以前做网站时,曾经需要实现一个图片上传到服务器前,先预览的功能.当时用html的<input type="file"/>标签一直实现不了,最后舍弃了这个标签,使用了 ...
- ASP.NET MVC图片上传前预览
回老家过春节,大半个月,在家的日子里,吃好睡好,人也长了3.5Kg.没有电脑,没有网络,无需写代码,工作上相关的完全放下......开心与父母妻儿过个年,那样的生活令Insus.NET现在还在留恋.. ...
- 本地图片上传与H5适配知识
最近用到本地图片上传作为API的参数,在网上看了许多,记录一下,以后可能用的着(仅自己记录用,看不清请绕路) function getObjectURL(file) { var url = null ...
- file标签 - 图片上传前预览 - FileReader & 网络图片转base64和文件流
记得以前做网站时,曾经需要实现一个图片上传到服务器前,先预览的功能.当时用html的<input type="file"/>标签一直实现不了,最后舍弃了这个标签,使用了 ...
- 前端的图片压缩image-compressor(可在图片上传前实现图片压缩)
https://www.imooc.com/article/40038 https://www.jianshu.com/p/3ce3e3865ae2 前端的图片压缩image-compressor(可 ...
- input file实现多选,限制文件上传类型,图片上传前预览功能
限制上传类型 & 多选:① accept 属性只能与 <input type="file" /> 配合使用.它规定能够通过文件上传进行提交的文件类型. ② mu ...
随机推荐
- sass用法快速入门
1.@mixin用法 (混合样式) 2.定义变量用$ (可作为全局变量使用) 命名规范 —— 遵守语义化命名:lg-大号.md-中号.base-基本号.sm-小号.mini-超小号 $font ...
- 复习-css边框和背景属性
css边框和背景属性 border:所有边框属性 border-width:四条边框的宽度 border-style:设置边框样式,主要有dotted.solid.double border-colo ...
- rds下载备份集
python版本[testuser@localhost tmp]$ python -VPython 2.7.5 需要提前安装RDS[root@localhost ~]# yum -y install ...
- bash的基础特性
命令历史:history 环境变量: HISTSIZE: 命令历史的条数 HISTFILE:~/.bash_history HISTFILESIZE: 命令历史文件记录历史的条数 history -d ...
- .Net 读取配置文件 xml
直接解析XML文件 1.System.Xml.Linq命名空间下提供可以使用linq查询的类,使用linq to xml读取也很方便. 2.还可以使用System.Xml.Serialization类 ...
- jQuery validator plugin之Validator
Validator.destroy() Destroys this instance of validator freeing up resources and unregistering event ...
- 解决Intellij IDEA中console窗口中文乱码的问题
配置完tomcat之后,测试运行时,中文是乱码,如下图(自己忘截图了,图源网络,看水印) 网上其他的修改方法我就不说了,至少我试了一个都没用. 下面两个方法也是网上的,在此总结一下: 1.在idea. ...
- 算法笔记--极大极小搜索及alpha-beta剪枝
参考1:https://www.zhihu.com/question/27221568 参考2:https://blog.csdn.net/hzk_cpp/article/details/792757 ...
- Java实现将文件或者文件夹压缩成zip
最近碰到个需要下载zip压缩包的需求,于是我在网上找了下别人写好的zip工具类.但找了好多篇博客,总是发现有bug.因此就自己来写了个工具类. 这个工具类的功能为: ( ...
- LeetCode--017--电话号码的字母组合(java)
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合. 给出数字到字母的映射如下(与电话按键相同).注意 1 不对应任何字母. 示例: 输入:"23" 输出:[&quo ...