前言
一个简单的用户上传头像的例子
功能:选择图片,设置裁剪位置,实时预览
一、安装和引入
安装
//npm安装
npm install vue-cropper
引入
<script>
import { VueCropper } from 'vue-cropper'
export default {
components: { VueCropper }
}
</script>
二、Events And Methods
Events
事件名 | 说明 | 参数 |
---|---|---|
realTime | 实时预览 | { url, h, w, img, div, html } |
Methods
通过 this.$refs.cropper 调用
方法名 | 说明 | 参数 |
---|---|---|
getCropData | 获取截图的 base64 数据 | date |
getCropBlob | 获取截图的 blob 数据 | date |
rotateRight | 向右旋转90度 | - |
rotateLeft | 向左旋转90度 | - |
changeScale | 图片缩放(正数变大 负数变小) | - |
组件更多的属性和方法见文档 vue-cropper
三、简单使用
简单使用,部分代码
<el-row>
<el-col :span="12">
<div style="width: 760px;height: 480px">
<vueCropper @realTime="realTime" :img="option.img" :autoCrop="option.autoCrop" />
</div>
</el-col>
<el-col :span="6">
<div>实时预览图</div>
<div :style="previewStyle">
<div :style="previews.div">
<img :src="previews.url" :style="previews.img">
</div>
</div>
</el-col>
</el-row>
data() {
return {
previews: {},
previewStyle: {},
option: {
img: require("../assets/img/huihui.png"), // 裁剪图片的地址
autoCrop: true, // 是否默认生成截图框 (默认:false)
},
};
},
methods: {
// 实时预览
realTime(date) {
console.log(date)
// {
// url: "blob:http://localhost:8080/e82d8987-41f1-40d0-9b86-25d3d7caecc8",
// h: 341,
// w: 358,
// div: {
// height: "341px",
// width: "358px"
// },
// img: {
// height: "1200px",
// transform: "scale(0.3958333333333333)translate3d(-1657.2631578947369px, -1030.7368421052631px, 0px)rotateZ(0deg)",
// width: "1920px"
// }
// html: ...
// }
this.previewStyle = {
width: data.w + "px",
height: data.h + "px",
overflow: "hidden",
margin: "0",
}
this.previews = data
},
}
效果图
四、实际应用(含本地图片下载)
全部代码
<template>
<div class="main">
<el-row>
<el-col :span="12">
<div style="width: 760px;height: 480px">
<vueCropper ref="cropper" @realTime="realTime" :img="option.img" :outputSize="option.outputSize" :full="option.full" :canMove="option.canMove"
:canMoveBox="option.canMoveBox" :centerBox="option.centerBox" :autoCrop="option.autoCrop" :autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight" :fixedBox="option.fixedBox" :fixed="option.fixed" :fixedNumber="option.fixedNumber"
:outputType="option.outputType" />
</div>
<div class="mt10">
<el-upload class="mb10" action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
<el-button size="small"> 选择图片 <i class="el-icon-upload"></i> </el-button>
</el-upload>
<el-button icon="el-icon-crop" size="small" @click="finish">确定</el-button>
<el-button icon="el-icon-plus" size="small" @click="changeScale(1)"></el-button>
<el-button icon="el-icon-minus" size="small" @click="changeScale(-1)"></el-button>
<el-button icon="el-icon-refresh-left" size="small" @click="rotateLeft()"></el-button>
<el-button icon="el-icon-refresh-right" size="small" @click="rotateRight()"></el-button>
</div>
</el-col>
<el-col :span="6">
<div>实时预览图</div>
<div :style="previewStyle">
<div :style="previews.div">
<img :src="previews.url" :style="previews.img">
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
export default {
components: { VueCropper },
data() {
return {
previews: {},
previewStyle: {},
option: {
img: require("../assets/img/huihui.png"), // 裁剪图片的地址
autoCrop: true, // 是否默认生成截图框 (默认:false)
outputSize: 1, // 裁剪生成图片的质量 (默认:1)
full: false, // 是否输出原图比例的截图 选true生成的图片会非常大 (默认:false)
canMove: true, // 上传图片是否可以移动 (默认:true)
// canMoveBox: false, // 截图框能否拖动 (默认:true)
centerBox: true,//截图框是否被限制在图片里面 (默认:false)
autoCropWidth: 200, // 默认生成截图框宽度 (默认:80%)
autoCropHeight: 200, // 默认生成截图框高度 (默认:80%)
fixedBox: true, // 固定截图框大小 不允许改变 (默认:false)
fixed: true,//是否开启截图框宽高固定比例 (默认:false)
// fixedNumber: [2, 1],//截图框宽高比例 [宽,高](默认[1:1])
outputType: 'png' // 裁剪生成图片的格式 可选值 jpeg, png, webp
},
};
},
methods: {
// 覆盖默认的上传行为
requestUpload() {
},
// 上传预处理
beforeUpload(file) {
if (file.type.indexOf("image/") == -1) {
this.$message.error("文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。");
} else {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
this.option.img = reader.result;
};
}
},
realTime(data) { //实时预览
this.previewStyle = {
width: data.w + "px",
height: data.h + "px",
overflow: "hidden",
margin: "0",
borderRadius: "50%",
}
this.previews = data
},
finish() { // 下载/上传 预览图
let fileName = '裁剪图'
this.$refs.cropper.getCropBlob((data) => { //获取截图的 blob 数据
// 上传图片
// this.uploadImg(data, fileName)
// 下载图片
let url = window.URL.createObjectURL(data)
this.downloadIamge1(url, fileName) //本地下载方法1
// this.downloadIamge2(url, fileName) //本地下载方法2
});
// this.$refs.cropper.getCropData(url => { //获取截图的 base64 数据
// this.downloadIamge1(url, fileName) //本地下载方法1
// // this.downloadIamge2(url, fileName) //本地下载方法2
// })
},
// 上传图片
uploadImg(data, fileName) {
let formData = new FormData();
formData.append('file', data, fileName);
// 上传到服务器
// uploadAvatar(formData).then(rse => { })
},
downloadIamge1(url, fileName) { // 下载图片
let link = document.createElement('a')
link.style.display = 'none'
link.setAttribute('href', url)
link.setAttribute('download', fileName)
document.body.appendChild(link)
link.click()
document.body.removeChild(link) //下载完成移除元素
window.URL.revokeObjectURL(url) //释放掉blob对象
},
downloadIamge2(imgsrc, fileName) {//下载图片
let image = new Image();
// 解决跨域 Canvas 污染问题
image.setAttribute("crossOrigin", "anonymous");
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据
let a = document.createElement("a"); // 生成一个a元素
let event = new MouseEvent("click"); // 创建一个单击事件
a.href = url; // 将生成的URL设置为a.href属性
a.download = fileName; // 设置图片名称
a.dispatchEvent(event); // 触发a的单击事件
window.URL.revokeObjectURL(imgsrc) //释放掉blob对象
};
image.src = imgsrc;
},
// 向左旋转
rotateLeft() {
this.$refs.cropper.rotateLeft();
},
// 向右旋转
rotateRight() {
this.$refs.cropper.rotateRight();
},
// 图片缩放
changeScale(num) {
num = num || 1;
this.$refs.cropper.changeScale(num);
},
},
};
</script>
<style>
.main {
position: relative;
}
</style>
效果图