先上效果圖:
1、安裝vue-cropper
npm install --save vue-cropperjs
2、項目中引入使用:
(1)全局引入man.js
import Vue from 'vue'
import VueCropper from 'vue-cropper'
import 'cropperjs/dist/cropper.css'
Vue.use(VueCropper)
(2)組件中單獨引用
import VueCropper from 'vue-cropper'
import 'cropperjs/dist/cropper.css'
export default {
components: {
VueCropper
}
}
3、封裝組件
crop.vue
<template>
<section class="crop">
<el-row>
<el-col :span="18">
<div class="cropper-div">
<vueCropper
height="562px"
ref="cropper"
:img="imgUrl"
:outputSize="option.size"
:outputType="option.outputType"
:info="true"
:guides="true"
:high="option.high"
:fixed="option.fixed"
:full="option.full"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:fixedBox="option.fixedBox"
:fixedNumber="option.fixedNumber"
:maxImgSize="option.maxImgSize"
@realTime="realTime"
:infoTrue="option.infoTrue"
@imgLoad="imgLoad"
/>
</div>
</el-col>
<el-col :span="6">
<div class="oprate-data-div">
<div class="crop-img-box">
<img :src="modelSrc" />
</div>
<el-input v-model="cropData.offX" size="mini">
<template slot="prepend">X</template>
<template slot="append">px</template>
</el-input>
<el-input v-model="cropData.offY" size="mini">
<template slot="prepend">Y</template>
<template slot="append">px</template>
</el-input>
<el-input v-model="cropData.cropW" size="mini">
<template slot="prepend">Width</template>
<template slot="append">px</template>
</el-input>
<el-input v-model="cropData.cropH" size="mini">
<template slot="prepend">Height</template>
<template slot="append">px</template>
</el-input>
<div class="finish-btn">
<el-button type="primary" @click="getPoint">完成截取</el-button>
</div>
</div>
</el-col>
</el-row>
</section>
</template>
<script>
export default {
props: ['imgSrc'],
data () {
return {
modelSrc: '', // 裁剪後的圖片地址
cropData: {
offX: '', // 裁剪框相對圖片的x
offY: '', // 裁剪框相對圖片的y
cropW: '', // 裁剪框寬度
cropH: '', // 裁剪框高度
imgW: '', // 原圖片寬度
imgH: '' // 原圖片高度
}, // 裁剪圖片數據
pointData: {
x1: '',
y1: '',
x2: '',
y2: ''
}, // 裁剪框的座標數據
imgUrl: 'http://cdn.xyxiao.cn/Portrait_1.jpg', // 原圖片的地址
option: {
size: 1, // 生成圖片的質量
full: true, // 是否輸出原圖比例的截圖
outputType: "png", // 裁剪生成圖片的格式
canMove: false, // 上傳圖片是否可以移動
original: false, // 上傳圖片按照原始比例渲染
canMoveBox: true, // 截圖框能否拖動
autoCrop: true, // 是否默認生成截圖框
high: true, // 是否按照設備的dpr 輸出等比例圖片
autoCropWidth: 252, // 默認生成截圖框寬度
autoCropHeight: 140, // 默認生成截圖框高度
fixedBox: false, // 固定截圖框大小 不允許改變
infoTrue: false, // true 爲展示真實輸出圖片寬高 false 展示看到的截圖框寬高
fixed: false, // 是否開啓截圖框寬高固定比例
downImg: "#",
fixedNumber: [4, 3], // 截圖框的寬高比例
maxImgSize: 3000 // 圖片最大像素
},
}
},
methods: {
imgLoad (msg) {
console.log(msg);
},
// 實時預覽函數
realTime (data) {
let imgAxis = this.$refs.cropper.getImgAxis()
let cropAxis = this.$refs.cropper.getCropAxis()
let cropImgX = cropAxis.x1 - imgAxis.x1,
cropImgY = cropAxis.y1 - imgAxis.y1,
imgWidth = imgAxis.x2 - imgAxis.x1,
imgHeight = imgAxis.y2 - imgAxis.y1
this.cropData = {
offX: cropImgX,
offY: cropImgY,
cropW: data.w,
cropH: data.h,
imgW: imgWidth,
imgH: imgHeight
}
this.getCropImg()
},
// 獲取裁剪框中的圖片
getCropImg () {
if (this.option.outputType === "blob") {
this.$refs.cropper.getCropBlob(data => {
var img = window.URL.createObjectURL(data);
this.modelSrc = img;
});
} else {
this.$refs.cropper.getCropData(data => {
this.modelSrc = data;
});
}
},
// 獲取裁剪框座標
getPoint () {
if (!this.compute()) {
this.$message({
message: '選擇區域無效,請重新選擇!',
type: 'error'
});
} else {
this.pointData = this.compute()
console.log(this.pointData)
}
},
// 判斷裁剪框是否爲有效區域
compute () {
let x = this.cropData.offX,
y = this.cropData.offY,
w = this.cropData.cropW,
h = this.cropData.cropH,
W = this.cropData.imgW,
H = this.cropData.imgH,
x1 = (x / W),
y1 = (y / H),
x2 = ((x + w) / W),
y2 = ((y + h) / H)
if (x < 0) {
if (w + x < 0) {
return false
} else {
x1 = 0
}
}
if (x > W - w) {
if (x > W) {
return false
} else {
x2 = 1
}
}
if (y < 0) {
if (y + h < 0) {
return fasle
} else {
y1 = 0
}
}
if (y > H - h) {
if (y > H) {
return false
} else {
y2 = 1
}
}
return {
x1: x1,
y1: y1,
x2: x2,
y2: y2
}
}
}
}
</script>
<style scoped lang="less">
@import "./style.less";
</style>
style.less
.crop {
padding: 20px;
.cropper-div {
margin: 20px auto;
width: 800px;
height: 500px;
}
.oprate-data-div {
margin: 20px 50px 0 0;
.crop-img-box {
width: 100%;
height: 100px;
img {
max-height: 100%;
max-width: 100%;
}
}
.el-input {
margin-top: 10px;
}
.finish-btn {
margin-top: 20px;
text-align: center;
}
}
}