cropperjs - yangmengwen/cropperjs GitHub Wiki
先下载cropperjs,也可以直接npm cropperjs 在组件里引入cropperjs,我是把他写成一个组件引用,需要的同学可以自行设计 在需要的页面引入该组件
<--组件cropper.vue-->
<template>
<div id="demo">
<!-- 遮罩层 -->
<div class="container" v-show="panel">
<div>
<img id="image" :src="url" alt="Picture">
</div>
<button type="button" id="button" @click="commit" style="background:#1AAD19">确定</button>
<button type="button" id="cancel" @click="cancel">取消</button>
</div>
<div class="vue-box">
<div class="show">
<div class="picture" :style="'backgroundImage:url('+headerImage+')'"></div>
</div>
<input type="file" class="file" accept="image/*" capture="camera" multiple @change="change" v-if="appOs == 'android'">
<input type="file" class="file" accept="image/png,image/jpg,image/jpeg" @change="change" v-else>
</div>
</div>
</template>
<script>
import Cropper from "cropperjs";
export default {
props: {
// 定义的宽高比
widthRate: {
type: Number,
default: 21,
},
// 定义的宽高比
heightRate: {
type: Number,
default: 27
},
imgUrl: {
type: String,
default: function () {
return ''
}
},
postUrl: ''
},
mounted() {
//初始化这个裁剪框
var self = this;
var image = document.getElementById("image");
this.cropper = new Cropper(image, {
aspectRatio: 21/27,
autoCropArea: 0.8,
viewMode: 1,
guides: true,
cropBoxResizable: false, //是否通过拖动来调整剪裁框的大小
movable: true,
cropBoxMovable: false, //是否通过拖拽来移动剪裁框。
dragCrop: true,
dragMode: "move",//‘crop’: 可以产生一个新的裁剪框3 ‘move’: 只可以移动3 ‘none’: 什么也不处理
center: true,
zoomable: true, //是否允许放大图像。
zoomOnTouch: true,//是否可以通过拖动触摸来放大图像。
scalable: true,
background: false,
checkOrientation: true,//self.appOs == 'android' ? true : false,
checkCrossOrigin: true,
zoomable: true,
toggleDragModeOnDblclick: false,
rotatable: true,
ready: function() {
self.croppable = true;
}
});
},
methods: {
//取消上传
cancel() {
this.panel = false;
this.$emit('getStatus',true)
},
//创建url路径
getObjectURL(file) {
var url = null;
if (window.createObjectURL != undefined) {
// basic
url = window.createObjectURL(file);
} else if (window.URL != undefined) {
// mozilla(firefox)
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) {
// webkit or chrome
url = window.webkitURL.createObjectURL(file);
}
return url;
},
//input框change事件,获取到上传的文件
change(e) {
let that = this
let files = e.target.files || e.dataTransfer.files;
if (!files.length) return;
let type = files[0].type; //文件的类型,判断是否是图片
let size = files[0].size; //文件的大小,判断图片的大小
that.$alert('为了您能够顺利通过阿里实人认证,请勿使用手机拍摄已有照片,保证照片清晰,人物完整。')
if (that.imgCropperData.accept.indexOf(type) == -1) {
that.$alert("请选择我们支持的图片格式!");
that.cancel();
}else if (size > 5242880) {
// that.$alert("请选择5M以内的图片!"); //这里可以根据需要自己设置
// that.cancel();
}
that.picValue = files[0];
///////////////////////////////////
var canvas = document.createElement("canvas");
var img = new Image();
var mpImg = new mimage(this.picValue);
//图片方向,判断图片方向解决剪切之后图片旋转问题
if (!!window.webkitURL) {
img.src = window.webkitURL.createObjectURL(this.picValue);
} else {
img.src = window.URL.createObjectURL(this.picValue);
}
let _this = this;
this.imgOrientationfn(img, function (o) {
var w = img.width;
var h = img.height;
//需要上传的图片
mpImg.render(canvas, {
maxWidth: w,
maxHeight: h,
orientation: o
});
//上传图片
var dataurl = canvas.toDataURL("image/jpeg");
let newFile = _this.dataURLtoBlob(dataurl);
let originUrl = _this.getObjectURL(newFile);
//每次替换图片要重新得到新的url
if (_this.cropper) {
_this.cropper.replace(originUrl);
}
_this.panel = true;
_this.$emit('getStatus',false)
})
////////////////////////////////////
},
//确定提交
commit() {
var croppedCanvas;
var roundedCanvas;
if (!this.croppable) {
return;
}
// Crop
croppedCanvas = this.cropper.getCroppedCanvas();
// Round
roundedCanvas = this.getRoundedCanvas(croppedCanvas);
this.headerImage = roundedCanvas.toDataURL();
// console.log(this.headerImage)
//上传图片
this.postImg();
},
//canvas画图
getRoundedCanvas(sourceCanvas) {
let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
// let width = sourceCanvas.width;
// let height = sourceCanvas.height;
//这里设置的宽高是产品要求,如果没有具体尺寸要求可使用上面注释的宽高
let width = 210 * 4;
let height = 270 * 4;
canvas.width = width;
canvas.height = height;
if (this.Orientation == 6) {
context.rotate(90 * Math.PI / 180)
context.translate(0, -840)
}
context.imageSmoothingEnabled = true;
context.drawImage(sourceCanvas, 0, 0, width, height);
context.globalCompositeOperation = 'destination-in';
context.beginPath();
context.rect(0, 0, 210 * 4, 270 * 4);
context.fill();
return canvas;
},
//提交上传函数
postImg() {
let _this = this;
let blob = _this.dataURLtoBlob(this.headerImage);
// 生成FormData对象
let fd = new FormData();
// 注:此处 file 应和后台接收参数匹配
fd.append('file', blob, Date.now() + '.jpg');
_this.$loading(true);
api[_this.postUrl](fd, function (isSuccess, data, err) {
_this.$loading(false);
if (data.status == "200") {
_this.$emit('callback', data.body)
_this.panel = false;
} else {
_this.$tips(data.message);
}
});
//_this.destoried();
},
newBlob(data, datatype) {
var out;
try {
out = new Blob([data], {type: datatype});
} catch (e) {
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (e.name == 'TypeError' && window.BlobBuilder) {
var bb = new BlobBuilder();
bb.append(data.buffer);
out = bb.getBlob(datatype);
}
else if (e.name == "InvalidStateError") {
out = new Blob([data], {type: datatype});
}
else {
}
}
return out;
},
dataURLtoBlob(data) {
let self = this;
var tmp = data.split(',');
tmp[1] = tmp[1].replace(/\s/g, '');
var binary = atob(tmp[1]);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new self.newBlob(new Uint8Array(array), 'image/jpeg');
},
imgOrientationfn: function (file, cb) {
file.onload = function () {
var $this = $(file).exifLoad(function () {
var Orientation = $this.exif("Orientation");
if (undefined != Orientation && "" != Orientation && Orientation.length > 0) {
Orientation = Orientation[0];
} else {
Orientation = 0;
}
cb(Orientation);
});
}
},
}
</script>
<style>
.vue-box {
opacity: 0;
height: 4.26rem;
width: 3.3rem;
position: relative;
z-index: 1;
top: 0;
}
.vue-box .file {
width: 100%;
height: 100%;
position: absolute;
top: -2.5rem;
}
#demo #button,#demo #cancel {
position: absolute;
right: 0.8rem;
bottom: 1rem;
width: 1.4rem;
height: 0.6rem;
border: none;
border-radius: 5px;
background: #f95454;
color: #fff;
line-height: 0.6rem;
}
#demo #cancel{left:0.8rem;}
#demo .show {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
/* border: 1px solid #d5d5d5; */
}
#demo .picture {
width: 100%;
height: 100%;
overflow: hidden;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
}
#demo .container {
z-index: 9999;
position: fixed;
/* padding-top: 0; */
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 1);
width: 100%;
height: 100%;
}
#demo .container>div{
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
#demo #image {
max-width: 100%;
}
.cropper-view-box,
.cropper-face {
}
/*!
* Cropper.js v1.0.0-rc
* https://github.com/fengyuanchen/cropperjs
*
* Copyright (c) 2017 Fengyuan Chen
* Released under the MIT license
*
* Date: 2017-03-25T12:02:21.062Z
*/
.cropper-container {
font-size: 0;
line-height: 0;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
direction: ltr;
-ms-touch-action: none;
touch-action: none;
}
.cropper-container img {
display: block;
min-width: 0 !important;
max-width: none !important;
min-height: 0 !important;
max-height: none !important;
width: 100%;
height: 100%;
image-orientation: 0deg;
}
.cropper-wrap-box,
.cropper-canvas,
.cropper-drag-box,
.cropper-crop-box,
.cropper-modal {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.cropper-wrap-box {
overflow: hidden;
}
.cropper-drag-box {
opacity: 0;
background-color: #fff;
}
.cropper-modal {
opacity: 0.8;
background-color: #000;
}
.cropper-view-box {
display: block;
overflow: hidden;
width: 100%;
height: 100%;
outline: 1px solid #39f;
outline-color: rgba(51, 153, 255, 0.75);
}
.cropper-dashed {
position: absolute;
display: block;
opacity: 0.5;
border: 0 dashed #eee;
}
.cropper-dashed.dashed-h {
top: 33.33333%;
left: 0;
width: 100%;
height: 33.33333%;
border-top-width: 1px;
border-bottom-width: 1px;
}
.cropper-dashed.dashed-v {
top: 0;
left: 33.33333%;
width: 33.33333%;
height: 100%;
border-right-width: 1px;
border-left-width: 1px;
}
.cropper-center {
position: absolute;
top: 50%;
left: 50%;
display: block;
width: 0;
height: 0;
opacity: 0.75;
}
.cropper-center:before,
.cropper-center:after {
position: absolute;
display: block;
content: " ";
background-color: #eee;
}
.cropper-center:before {
top: 0;
left: -3px;
width: 7px;
height: 1px;
}
.cropper-center:after {
top: -3px;
left: 0;
width: 1px;
height: 7px;
}
.cropper-face,
.cropper-line,
.cropper-point {
position: absolute;
display: block;
width: 100%;
height: 100%;
opacity: 0.1;
}
.cropper-face {
top: 0;
left: 0;
background-color: #fff;
}
.cropper-line {
background-color: #39f;
}
.cropper-line.line-e {
top: 0;
right: -3px;
width: 5px;
cursor: e-resize;
}
.cropper-line.line-n {
top: -3px;
left: 0;
height: 5px;
cursor: n-resize;
}
.cropper-line.line-w {
top: 0;
left: -3px;
width: 5px;
cursor: w-resize;
}
.cropper-line.line-s {
bottom: -3px;
left: 0;
height: 5px;
cursor: s-resize;
}
.cropper-point {
width: 5px;
height: 5px;
opacity: 0.75;
background-color: #39f;
}
.cropper-point.point-e {
top: 50%;
right: -3px;
margin-top: -3px;
cursor: e-resize;
}
.cropper-point.point-n {
top: -3px;
left: 50%;
margin-left: -3px;
cursor: n-resize;
}
.cropper-point.point-w {
top: 50%;
left: -3px;
margin-top: -3px;
cursor: w-resize;
}
.cropper-point.point-s {
bottom: -3px;
left: 50%;
margin-left: -3px;
cursor: s-resize;
}
.cropper-point.point-ne {
top: -3px;
right: -3px;
cursor: ne-resize;
}
.cropper-point.point-nw {
top: -3px;
left: -3px;
cursor: nw-resize;
}
.cropper-point.point-sw {
bottom: -3px;
left: -3px;
cursor: sw-resize;
}
.cropper-point.point-se {
right: -3px;
bottom: -3px;
width: 20px;
height: 20px;
cursor: se-resize;
opacity: 1;
}
@media (min-width: 768px) {
.cropper-point.point-se {
width: 15px;
height: 15px;
}
}
@media (min-width: 992px) {
.cropper-point.point-se {
width: 10px;
height: 10px;
}
}
@media (min-width: 1200px) {
.cropper-point.point-se {
width: 5px;
height: 5px;
opacity: 0.75;
}
}
.cropper-point.point-se:before {
position: absolute;
right: -50%;
bottom: -50%;
display: block;
width: 200%;
height: 200%;
content: " ";
opacity: 0;
background-color: #39f;
}
.cropper-invisible {
opacity: 0;
}
.cropper-bg {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC");
}
.cropper-hide {
position: absolute;
display: block;
width: 0;
height: 0;
}
.cropper-hidden {
display: none !important;
}
.cropper-move {
cursor: move;
}
.cropper-crop {
cursor: crosshair;
}
.cropper-disabled .cropper-drag-box,
.cropper-disabled .cropper-face,
.cropper-disabled .cropper-line,
.cropper-disabled .cropper-point {
cursor: not-allowed;
}
</style>
<--页面中引入组件-->
<tempalte>
<div class="wrap">
<div class="yi" v-if="!!signupInfo.facePic">
<img class="sel-img" :src="signupInfo.facePic " />
<!-- <img class="sel-img" :src=" signupInfo.facePic " /> -->
<cropper-photo @callback="imgUrl" :postUrl="facepicUpload" @getStatus="getStatus"></cropper-photo>
<div class="di">点此上传</div>
</div>
</div>
</template>
<script>
import cropperPhoto from './cropper'
export default{
components: { cropperPhoto,uploadImg },
data(){
signupInfo: {
facePic:"",
compressFacePic: ''
},
}
methods: {
imgUrl(imgData){
this.signupInfo.facePic = imgData.url;//原始图片地址
this.signupInfo.compressFacePic = imgData.resizedUrl;//改变尺寸后的图片地址
// this.signupInfo.facePic = this.host.OP_KB + '/employee/view/img/download?fileName=' + cosUrl;
// console.log(this.signupInfo.facePic,this.signupInfo.compressFacePic)
},
}
}
</script>