原本在網上找的截圖插件已經可以滿足截圖需求了,但是後面,需求又增加了。要有圖檔壓縮的功能,還有能選原圖或者截圖。是以把代碼改了一下(後續可能還會修改):
引入CSS、JS:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropper/3.1.3/cropper.min.css" target="_blank" rel="external nofollow" >
<script src="https://cdn.bootcss.com/jquery/2.1.0-beta3/jquery.min.js"></script>
<script src="http://malsup.github.io/jquery.form.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropper/3.1.3/cropper.min.js"></script>
CSS:
@charset 'utf-8';
.btn {
display: inline-block;
text-align: center;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
padding: 6px 12px;
background: transparent;
border: 0;
border-radius: 4px;
}
.btn-demo {
height: 35px;
background-color: #d9534f;
border: #d9534f;
color: #fff;
/*margin: 20px;*/
}
.update-bg {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.5);
display: none;
}
.update-bg .btn {
display: inline-block;
text-align: center;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
padding: 6px 12px;
background: transparent;
border: 0;
border-radius: 4px;
}
.update-bg .clearfix:after {
display: block;
content: '';
clear: both;
}
.update-bg .update-wrapper {
position: relative;
margin: 50px auto;
width: 900px;
min-height: 580px;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
border-radius: 6px;
}
.update-bg .update-wrapper .update-header {
padding: 15px;
min-height: 20px;
border-bottom: 1px solid #e5e5e5;
}
.update-bg .update-wrapper .update-header .text {
font-size: 18px;
font-weight: 500;
float: left;
}
.update-bg .update-wrapper .update-header .close {
float: right;
padding: 0;
font-size: 22px;
color: #000;
text-shadow: 0 1px 0 #fff;
font-weight: bold;
opacity: .2;
}
.update-bg .update-wrapper .update-main {
padding: 15px 30px;
}
.update-bg .update-wrapper .update-main .update-btn {
height: 35px;
background-color: #d9534f;
border: #d9534f;
color: #fff;
}
.update-bg .update-wrapper .update-main .update-body {
margin-top: 15px;
}
.update-bg .update-wrapper .update-main .update-body .body-left {
float: left;
width: 620px;
height: 360px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.25);
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.25);
background-color: #fcfcfc;
overflow: hidden;
}
.update-bg .update-wrapper .update-main .update-body .body-left .update-img {
display: none;
}
.update-bg .update-wrapper .update-main .update-body .body-right {
float: right;
width: 180px;
height: 180px;
border: 1px solid #eee;
border-radius: 4px;
background-color: #fff;
overflow: hidden;
}
.update-bg .update-wrapper .update-main .update-body .body-right .user-header {
display: none;
}
.update-bg .update-wrapper .update-main .operation-wrapper {
margin-top: 15px;
}
.update-bg .update-wrapper .update-main .operation-wrapper .operation-left {
float: left;
width: 620px;
}
.update-bg .update-wrapper .update-main .operation-wrapper .operation-left .btn {
height: 35px;
background-color: #d9534f;
border: #d9534f;
color: #fff;
}
.update-bg .update-wrapper .update-main .operation-wrapper .operation-left .left-container {
float: left;
}
.update-bg .update-wrapper .update-main .operation-wrapper .operation-left .left-container .btn {
margin-right: 10px;
}
.update-bg .update-wrapper .update-main .operation-wrapper .operation-left .right-container {
float: right;
}
.update-bg .update-wrapper .update-main .operation-wrapper .operation-left .right-container .btn {
margin-left: 10px;
}
.update-bg .update-wrapper .update-main .operation-wrapper .operation-right {
float: right;
width: 180px;
}
.update-bg .update-wrapper .update-main .operation-wrapper .operation-right .btn {
width: 100%;
height: 35px;
background-color: #d9534f;
border: #d9534f;
color: #fff;
}
.pic-cont {
display: flex;
justify-content: center;
align-items: center;
width: 180px;
height: 180px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
#J-user-header-img {
width: auto;
height: 100%;
}
.btn-demo {
display: flex;
margin-top: 10px;
}
HTML:
<!-- 上傳圖檔-截圖 -->
<div class="pic-cont">
<img src="" alt="" id="J-user-header-img">
</div>
<button class="btn btn-demo" id="J-demo">上傳圖檔</button>
<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>
<input id="artwork" name="img" type="radio" value="" checked="checked" /> 原圖
<input id="cropper" name="img" type="radio" value="" /> 截圖
</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>
JS:
'use strict';
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var imgInfo = {
width: null,
height: null,
rotate: 0,
scale: 1
};
var imgArtwork = ''
var cropperIng = void 0;
// jq對象 cropper的宿主
var cropperTarget = void 0;
// jq對象 裁剪實時呈現的效果圖像
var userImg = void 0;
// 裁剪圖檔功能封裝類
var UpdateCropper = function () {
// 回調方法
function UpdateCropper(callBack) {
_classCallCheck(this, UpdateCropper);
this.callBack = callBack;
}
_createClass(UpdateCropper, [{
key: 'init',
value: function 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();
}
}, {
key: 'addEvent',
value: function addEvent() {
var _this2 = this;
var _this = this;
$('#J-update-img-file').on('change', function (e) {
if (!this.files[0] || !window.FileReader) return
if (this.files[0].type !== 'image/jpeg') {
alert('請選擇jpg格式的圖檔!');
return
}
// 建立一個reader
const reader = new FileReader()
const that = this
// 将圖檔轉成base64格式
reader.readAsDataURL(this.files[0])
// 讀取成功後的回調
reader.onloadend = function () {
const result = this.result
const img = new Image()
img.src = result
console.log("********未壓縮前的圖檔大小********")
console.log(result)
console.log(result.length)
img.onload = function () {
const data = compress(img, 0.1) // - 圖檔品質:取值範圍為0到1
console.log("********壓縮後的圖檔大小********")
console.log(data)
console.log(data.length)
var imgSrc = data
imgArtwork = data
_this.createCropper(imgSrc)
}
}
});
$('#J-update-wrapper').on('click', '.J-close', function () {
_this2.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', function () {
_this2.getCroppedCanvas();
});
// J-close
}
}, {
key: 'destroy',
value: function destroy() {
this.removeEvent();
cropperTarget.cropper('destroy');
userImg.attr('src', '').hide();
cropperTarget.attr('src', '').hide();
$('#J-update-wrapper').fadeOut('slow');
// $('#J-update-wrapper').hide();
}
}, {
key: 'removeEvent',
value: function removeEvent() {
$('#J-update-img-file').off();
$('#J-update-wrapper').off();
}
/**
* 建立cropper容器 巴拉巴拉
* @param {string} src
*/
}, {
key: 'createCropper',
value: function createCropper(src) {
var _this3 = this;
document.getElementById('J-update-img').onload = function () {
var 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, // 類型:Number,預設值NaN。設定剪裁容器的比例
viewMode: 1,
// 建立 使用者操作都會改變顯示對象
crop: function crop(e) {
// console.log('=.=', e)
_this3.changeImg(e);
}
});
};
cropperTarget.attr('src', src).show();
}
// 右側顯示對象改變
}, {
key: 'changeImg',
value: function changeImg(detail) {
// console.log('====', detail)
var 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'
});
}
// 操作方法
}, {
key: 'operation',
value: function operation(target) {
if (!cropperIng) {
return;
}
var type = target.data('type');
switch (type) {
case 'rote-left':
imgInfo.rotate -= 90;
$('#J-update-img').cropper('rotate', -90);
break;
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輸出
}, {
key: 'getCroppedCanvas',
value: function getCroppedCanvas() {
if (!cropperIng) {
return;
}
console.log('...', imgArtwork)
var base64 = ''
// 原圖
if (!$("#artwork[type='radio']").is(':checked')) {
var cas = cropperTarget.cropper('getCroppedCanvas');
base64 = cas.toDataURL('image/jpeg');
this.callBack(base64);
this.destroy();
} else {
base64 = imgArtwork;
this.callBack(base64);
this.destroy();
}
const blob = dataURItoBlob(base64)
const formData = new FormData()
var nameImg = new Date().getTime() + '.jpg'
formData.append('file', blob, nameImg)
var uploadUrl = '' // 上傳圖檔接口位址
// 請求背景接口
$.ajax({
url: uploadUrl,
type: "POST",
data: formData,
success: function (data) {
console.log(data)
}
})
}
}]);
return UpdateCropper;
}();
// 壓縮圖檔
function compress(img, compressNum) {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
const width = img.width
const height = img.height
canvas.width = width
canvas.height = height
// 鋪底色
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(img, 0, 0, width, height)
// 進行壓縮 compressNum - 圖檔品質:取值範圍為0到1
const ndata = canvas.toDataURL('image/jpeg', compressNum)
return ndata
}
// base64轉成bolb對象
function dataURItoBlob(base64Data) {
var byteString
if (base64Data.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(base64Data.split(',')[1])
} else {
byteString = unescape(base64Data.split(',')[1])
}
var mimeString = base64Data
.split(',')[0]
.split(':')[1]
.split(';')[0]
var ia = new Uint8Array(byteString.length)
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
return new Blob([ia], {
type: mimeString
})
}
點選時調用:
// 上傳圖檔-截圖
var update;
$('#J-demo').click(function () {
if (!update) {
update = new UpdateCropper((base64url) => {
$('#J-user-header-img').attr('src', base64url);
});
}
update.init();
});