最近有個專案要在瀏覽器端裁剪并上傳圖片,由于缺乏人力,只能我上陣殺敵,通過參考各種文章,最后決定用cropperjs進行圖片裁剪,用webuploader上傳檔案,本文涉及到的知識至少有Java基礎、SpringMVC、thymeleaf模版引擎、JS基礎、JQuery基礎、Bootstrap組件,但是文章重點只是cropperjs和webuploader的組合運用,其他的都是輔助,
1. 依賴JS庫
webuploader官網
cropperjs演示主頁
cropperjs開源主頁
2. 核心流程
- 2.1 選擇檔案按鈕
previewImg用于預覽上傳后的圖片;picker用于選擇圖片,webuploader會自動給picker賦予選擇檔案的特性,fileInput用于接收檔案資料,
<div >
<img id="previewImg" />
<div>
<a href="javascript:void(0)" id="picker">選擇圖片</a>
<input type="file" id="fileInput" style="display: none" />
</div>
</div>
下面代碼給fileInput組件觸發了點擊事件
$("#picker").on('click', function () {
$("#fileInput").trigger("click");
});
- 2.2 定義組件引數和事件
以下代碼定義上傳組件物件
var uploader = WebUploader.create({
auto: true,// 選完檔案后,是否自動上傳,
server: '/upload',
fileSingleSizeLimit: 2 * 1024 * 1024,
duplicate: true,
accept: {// 只允許選擇圖片檔案,
title: 'Images',
extensions: 'jpg,jpeg,png',
mimeTypes: 'image/jpg,image/jpeg,image/png'
},
//如果有表單資料要上傳,可以給formData賦值
formData: {
id: 0
}
});
以下代碼定義上傳組件事件,WebUploader組件不提供UI,如果需要定制界面,實作下面的方法即可,
//提交額外的表單資料
uploader.on('uploadBeforeSend', function (object, data, header) {
data.id = $('#id').val();
});
// 當有檔案被添加進佇列的時候
uploader.on('fileQueued', function (file) {
$('#file_list').append('<div id="' + file.id + '" >' +
'<h4 >' + file.name + '</h4>' +
'<p >等待上傳...</p>' +
'</div>');
});
// 上傳成功
uploader.on('uploadSuccess', function (file, response) {
$('#' + file.id).find('p.state').text('已上傳');
console.log(response._raw);
var object = $.parseJSON(response._raw);
//給預覽組件賦值
$('#previewImg').attr("src", object.url);
});
// 上傳發生錯誤
uploader.on('uploadError', function (file) {
$('#' + file.id).find('p.state').text('上傳出錯');
});
// 上傳中
uploader.on('startUpload', function (file, rs) {
console.log("檔案正在上傳中,請稍候");
});
- 2.3 定義裁剪組件引數和事件
以下代碼定義裁剪圖片的對話框,cropperImage是上傳后的圖片,被裁剪的目標物件,
<div id="cropperImageModal" tabindex="-1" role="dialog" aria-labelledby="cropperImageModal"
aria-hidden="true">
<div style="width: 50%;">
<div >
<div >
<button type="button" data-dismiss="modal" aria-hidden="true">×</button>
<h4 >裁剪圖片</h4>
</div>
<div >
<!-- cropperImage是上傳后的圖片,被裁剪的目標物件 -->
<img src="" id="cropperImage" style="max-width: 100%"/>
</div>
<div >
<button type="button" data-dismiss="modal" id="modalClose">關閉</button>
<button type="button" id="modalSubmit">保存</button>
</div>
</div>
</div>
</div>
以下代碼定義圖片裁剪引數,更多引數參考cropper.js的API詳解,如果不需要固定裁剪區域大小,洗掉ready函式即可,
var cropperImage = $("#cropperImage");
var cropperOptions = {
viewMode: 1,
dragMode: 'none',
aspectRatio: 1,
background: false,
autoCropArea: 0.6,
crop: function (event) {
//裁剪的實時事件
console.log(event.detail.width);
console.log(event.detail.height);
},
ready: function () {
//限定裁剪區域大小為500
cropperImage.cropper('crop');
cropperImage.cropper('setData', {
width: 500,
height: 500
})
}
};
- 2.5 觸發裁剪和上傳事件
fileInput組件的change事件會采用FileReader物件獲得上傳的Image,初始化cropperjs裁剪方法,
$("#fileInput").on('change', function () {
var file = this.files[0];
//定義讀檔案物件
var reader = new FileReader();
reader.onload = function () {
imageOnload(reader.result);
};
reader.readAsDataURL(file);//File物件轉換為dataURL
});
//圖片物件加載方法
function imageOnload(url) {
var cropperImg = new Image();
cropperImg.src = https://www.cnblogs.com/xiaoyangjia/p/url;
//destroy方法是為了重入不出錯
cropperImage.cropper('destroy').attr('src', url).cropper(cropperOptions);
cropperImg.onload = function () {
//彈窗裁剪
$('#cropperImageModal').modal();
$("#modalClose").on('click', function () {
$("#fileInput").val('');
$('#cropperImageModal').modal('hide');
});
$("#modalSubmit").on('click', function () {
var canVas = $("#cropperImage").cropper("getCroppedCanvas", {});//獲取裁剪后得到的canvas資料
var file = convertBase64UrlToBlob(canVas.toDataURL('image/jpeg', '0.0'));//將canvas轉換為Blob格式
uploader.addFiles(file);//將裁剪后的圖片添加進webuploader上傳到后臺
$('#cropperImageModal').modal('hide');
$("#fileInput").val('');
});
};
}
采用cropperImage.cropper('getCroppedCanvas').toblob(function(blob){})也可以獲取圖片二進制物件,但是默認是png格式,體積很大,不利于網路傳輸,采用下面的方法可以指定圖片格式,
/**
* base64轉為blob,圖片為jpeg格式
*/
function convertBase64UrlToBlob(urlData) {
//去掉url的頭,并轉換為byte
var bytes = window.atob(urlData.split(',')[1]);
//處理例外,將ascii碼小于0的轉換為大于0
var ab = new ArrayBuffer(bytes.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], {type: 'image/jpeg'});
}
- 2.6 后端介面實作
@Controller
public class IndexController {
protected final Logger logger = LoggerFactory.getLogger(getClass());
@RequestMapping("/index")
public String list(ModelMap map) {
return "index";
}
@PostMapping("/upload")
@ResponseBody
public UploadFileVo uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("id") Integer id, HttpServletResponse response) {
response.setContentType("text/html");
//保存圖片到服務端,回傳訪問地址
UploadFileVo uploadFileVo = new UploadFileVo();
//這里為了演示,回傳一張網圖
uploadFileVo.setUrl("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
logger.info("上傳成功,url:{},id:{}", uploadFileVo.getUrl(), id);
return uploadFileVo;
}
}
- 2.7 最終效果圖

3. 完整代碼
查閱演示代碼
參考
https://www.codingbrick.com/archives/456.html
作者:編碼磚家公眾號:編碼磚家
出處:https://www.cnblogs.com/xiaoyangjia/
本文著作權歸作者所有,任何人或團體、機構全部轉載或者部分轉載、摘錄,請在文章明顯位置注明作者和原文鏈接,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/452042.html
標籤:JavaScript
