上傳圖片裁剪外掛(基於cropper.js的封裝)
阿新 • • 發佈:2019-01-02
如題,這樣的功能在開發中是非常常見的,cropper.js是一款很好的工具,網上都有詳細的介紹,這篇文章提示很多友好的API和事件cropper.js 裁剪圖片並上傳(文件翻譯+demo)
cropper.js需要藉助jquery來實現,所以我這裡的樣式抄襲了jquery頭像上傳剪裁外掛cropper這個工具,具體功能沒有copy,只是覺得這一款介面符合使用者體驗,可以實時看到自己的裁剪效果(利用css3特性)
不多說上程式碼,樣式上我用scss寫的,反正最終是webpack打包的^_^,不支援ie9以下
html主要程式碼
<div class="update-bg" id ="J-update-wrapper">
<input type="file" id="J-update-img-file" style="display: none">
<div class="update-wrapper">
<div class="update-header clearfix">
<h3 class="text">上傳圖片</h3>
<button class="btn close J-close">x</button>
</div >
<div class="update-main">
<button class="btn update-btn J-update-btn">請選擇圖片</button>
<div class="update-body clearfix">
<div class="body-left">
<img id="J-update-img" class="update-img" src="" alt="" >
</div>
<div class="body-right">
<img src="" class="user-header" id="J-update-user-header">
</div>
</div>
<div class="operation-wrapper clearfix">
<div class="operation-left">
<div class="left-container">
<button class="btn J-operation-btn" data-type="rote-left">向左旋轉</button>
<button class="btn J-operation-btn" data-type="rote-right">向右旋轉</button>
</div>
<div class="right-container">
<button class="btn J-operation-btn" data-type="scale-b">放大</button>
<button class="btn J-operation-btn" data-type="scale-s">縮小</button>
</div>
</div>
<div class="operation-right">
<button class="btn J-operation-save">儲存圖片</button>
</div>
</div>
</div>
</div>
</div>
scss程式碼
// 主色調
$btnColor: $basic_color;
.update-bg {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, .7);
display: none;
z-index: 999;
.btn {
display: inline-block;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
padding: 6px 12px;
background: transparent;
border: 0;
border-radius: 4px;
}
.clearfix:after {
display: block;
content: '';
clear: both;
}
.update-wrapper {
position: relative;
margin: 50px auto;
width: 900px;
min-height: 580px;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
border-radius: 6px;
.update-header {
padding: 15px;
min-height: 20px;
border-bottom: 1px solid #e5e5e5;
.text {
font-size: 18px;
font-weight: 500;
float: left;
}
.close {
float: right;
padding: 0;
font-size: 22px;
color: #000;
text-shadow: 0 1px 0 #fff;
font-weight: bold;
opacity: .2;
}
}
.update-main {
padding: 15px 30px;
.update-btn {
height: 35px;
background-color: $btnColor;
border: $btnColor;
color: #fff;
}
.update-body {
margin-top: 15px;
.body-left {
float: left;
width: 620px;
height: 360px;
box-shadow: inset 0 0 5px rgba(0,0,0,.25);
background-color: #fcfcfc;
overflow: hidden;
.update-img {
display: none;
width: 0;
height: 0;
}
}
.body-right {
float: right;
width: 180px;
height: 180px;
border: 1px solid #eee;
border-radius: 4px;
background-color: #fff;
overflow: hidden;
.user-header {
display: none;
max-width: none;
height: auto;
}
}
}
.operation-wrapper {
margin-top: 15px;
.operation-left {
float: left;
width: 620px;
.btn {
height: 35px;
background-color: $btnColor;
border: $btnColor;
color: #fff;
}
.left-container {
float: left;
.btn {
margin-right: 10px;
}
}
.right-container {
float: right;
.btn {
margin-left: 10px;
}
}
}
.operation-right {
float: right;
width: 180px;
.btn {
width: 100%;
height: 35px;
background-color: $btnColor;
border: $btnColor;
color: #fff;
}
}
}
}
}
}
js部分
// 重置樣式
import 'common/style/reset.styl';
import './index.scss';
// cropper引入 樣式和js檔案都需要哦
import '../../../node_modules/cropper/dist/cropper.min.css';
import '../../../node_modules/cropper/dist/cropper.min.js';
// 儲存上傳圖片的資訊
const imgInfo = {
width: null,
height: null,
rotate: 0
};
// 哨兵變數 對按鈕的響應作判斷
let cropperIng;
// jq物件 cropper的宿主
let cropperTarget;
// jq物件 裁剪實時呈現的效果影象
let userImg;
// 裁剪圖片功能封裝類
export default class UpdateCropper {
// 回撥方法
constructor(callBack) {
this.callBack = callBack;
}
// 初始化
init() {
imgInfo.width = null;
imgInfo.height = null;
imgInfo.rotate = 0;
imgInfo.scale = 1;
cropperIng = false;
cropperTarget = $('#J-update-img');
userImg = $('#J-update-user-header');
$('#J-update-wrapper').fadeIn('slow');
this.addEvent();
}
// 新增事件
addEvent() {
const _this = this;
$('#J-update-img-file').on('change', function (e) {
// 這樣的操作不支援ie9及以下
if (!this.files[0].type.match(/image.*/)) {
alert('請選擇正確的圖片!');
}
const imgSrc = URL.createObjectURL(this.files[0]);
_this.createCropper(imgSrc);
});
$('#J-update-wrapper').on('click', '.J-close', () => {
this.destroy();
});
$('#J-update-wrapper').on('click', '.J-update-btn', function() {
document.getElementById('J-update-img-file').click();
});
// 操作按鈕
$('#J-update-wrapper').on('click', '.J-operation-btn', function() {
_this.operation($(this));
});
$('#J-update-wrapper').on('click', '.J-operation-save', () => {
this.getCroppedCanvas();
});
// J-close
}
// 銷燬
destroy() {
this.removeEvent();
cropperTarget.cropper('destroy');
userImg.attr('src', '').hide();
cropperTarget.attr('src', '').hide();
$('#J-update-wrapper').fadeOut('slow');
// $('#J-update-wrapper').hide();
}
// 移除事件
removeEvent() {
$('#J-update-img-file').off();
$('#J-update-wrapper').off();
}
/**
* 建立cropper容器 巴拉巴拉
* @param {string} src
*/
createCropper(src) {
document.getElementById('J-update-img').onload = () => {
const elem = document.getElementById('J-update-img');
// 獲取圖片真實寬高,用於後期比例計算
imgInfo.width = elem.naturalWidth;
imgInfo.height = elem.naturalHeight;
userImg.attr('src', src).show();
cropperIng = true;
cropperTarget.cropper('destroy');
cropperTarget.cropper({
aspectRatio: 9 / 9,
viewMode: 1,
// 建立 使用者操作都會改變顯示物件
crop: (e) => {
this.changeImg(e.detail);
}
});
};
cropperTarget.attr('src', src).show();
}
// 右側顯示物件改變
changeImg(detail) {
const num = 180 / detail.width;
userImg.css({
transform: `translate(-${detail.x * num}px, -${detail.y * num}px) rotate(${imgInfo.rotate}deg)`,
width: `${imgInfo.width * num}px`,
height: `${imgInfo.heigh * num}px`
});
}
// 操作方法 旋轉縮放都是在基於上一次操作的基礎上
operation(target) {
if (!cropperIng) {
return;
}
const type = target.data('type');
switch (type) {
// 左旋90度
case 'rote-left':
imgInfo.rotate -= 90;
$('#J-update-img').cropper('rotate', -90);
break;
// 右旋90度
case 'rote-right':
imgInfo.rotate += 90;
$('#J-update-img').cropper('rotate', 90);
break;
// 放大一下下
case 'scale-b':
$('#J-update-img').cropper('zoom', 0.1);
break;
case 'scale-s':
// 縮小一下下
$('#J-update-img').cropper('zoom', -0.1);
break;
}
}
// 轉換成base64輸出
getCroppedCanvas() {
if (!cropperIng) {
return;
}
const cas = cropperTarget.cropper('getCroppedCanvas');
const base64 = cas.toDataURL('image/jpeg');
this.callBack(base64);
this.destroy();
}
}
演示一下效果(GIF圖)
縮放,裁剪,旋轉這些基本功能都全了,如果有興趣可以拓展
github地址
專案github地址 大致思路就是這樣,如果有其它功能就自行拓展吧~