感觉这个挺有意思的,所以就弄了,也需要了几个知识点,顺带学习了,记录一下。
主要用到的是 vue-cropper 截图插件,具体的安装,引入,使用请看 vue-cropper官方文档 ,很详细了,这里不赘述。
效果如图:
在硬菜之前先来点前菜吧,使用中遇到的东西,记录一下:
1,FileReader 函数
FileReader
对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用File
或Blob
对象指定要读取的文件或数据。FileReader仅用于以安全的方式从用户(远程)系统读取文件内容 它不能用于从文件系统中按路径名简单地读取文件。
通俗来讲,FileReader 函数是用来异步读取计算机上的文件的,可以将文件读取为不同的形式,具体读取形式取决于使用何种方法:
- 将选择文件读取为 ArrayBuffer 数据对象:
FileReader.readAsArrayBuffer()
- 将选择文件读取为原始二进制数据:
FileReader.readAsBinaryString()
- 将选择文件读取为URL格式的Base64字符串:
FileReader.readAsDataURL()
- 将选择文件读取为字符串:
FileReader.readAsText()
详细内容请看: FileReader() MDN,
2,URL.createObjectURL 方法
URL.createObjectURL静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document绑定。这个新的URL 对象表示指定的
File
对象或Blob
对象。该方法的参数:用于创建 URL 的
File
对象、Blob
对象或者MediaSource
对象。通俗来讲,URL.createObjectURl方法用于为传入该方法的参数对象创建URL,可以干什么呢,比如预览(赋值给img的src属性),下载(a标签href属性)。
详情内容请看: URL.createObjectURL MDN。
关于以上两种方法的使用参见下面的图片截取操作。
更多内容推荐一篇文章: Blob、File、FileReader 和 Data URL。
上硬菜:
<template>
<div class="cropper-content">
<div class="cropper-box">
<div class="cropper">
<vue-cropper
ref="cropper"
:img="option.img"
:outputSize="option.outputSize"
:outputType="option.outputType"
:info="option.info"
:canScale="option.canScale"
:autoCrop="option.autoCrop"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:full="option.full"
:fixedBox="option.fixedBox"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:centerBox="option.centerBox"
:height="option.height"
:infoTrue="option.infoTrue"
:maxImgSize="option.maxImgSize"
:enlarge="option.enlarge"
:mode="option.mode"
@realTime="realTime"
@imgLoad="imgLoad">
</vue-cropper>
</div>
<!--底部操作工具按钮-->
<div class="footer-btn">
<div class="scope-btn">
<label class="btn" for="uploads">选择图片</label>
<input type="file"
id="uploads"
style="position:absolute; clip:rect(0 0 0 0);display: none;"
accept="image/png, image/jpeg, image/gif, image/jpg"
@change="selectImg($event)">
<button size="mini" type="danger" plain @click="cropImageStart">开始</button>
<button size="mini" type="danger" plain @click="cropImageStop">拖动</button>
<button size="mini" type="danger" plain @click="cropImageClear" style="margin-right: 5px;">清除</button>
<button size="mini" type="danger" plain icon="el-icon-zoom-in" @click="changeScale(1)">放大</button>
<button size="mini" type="danger" plain icon="el-icon-zoom-out" @click="changeScale(-1)">缩小</button>
<button size="mini" type="danger" plain @click="rotateLeft">↺ 左旋转</button>
<button size="mini" type="danger" plain @click="rotateRight">↻ 右旋转</button>
</div>
<div class="upload-btn">
<button size="mini" type="success" @click="uploadImg('blob')">上传封面 <i class="el-icon-upload"></i></button>
<button size="mini" type="danger" plain @click="downloadImage('blob')">下载</button>
</div>
</div>
</div>
<!--预览效果图-->
<div class="show-preview">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img">
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.cropper-content{
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.cropper-box{
flex: 1;
width: 100%;
.cropper{
width: auto;
height: 300px;
}
}
.show-preview{
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
.preview{
overflow: hidden;
border:1px solid #67c23a;
background: #cccccc;
}
}
}
.footer-btn{
margin-top: 30px;
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.scope-btn{
display: flex;
display: -webkit-flex;
justify-content: space-between;
padding-right: 10px;
}
.upload-btn{
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
}
.btn {
outline: none;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
-webkit-transition: .1s;
transition: .1s;
font-weight: 500;
padding: 8px 15px;
font-size: 12px;
border-radius: 3px;
color: #fff;
background-color: #409EFF;
border-color: #409EFF;
margin-right: 10px;
}
}
</style>
<script>
import { VueCropper } from 'vue-cropper'
import upload from '@/http/upload'
export default {
name: "CropperImage",
components: {
VueCropper
},
props:['Name'],
data() {
return {
name:this.Name,
previews: {},
fileName: "",
option:{
img: '', //裁剪图片的地址
outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1)
outputType: 'jpeg', //裁剪生成图片的格式(jpeg || png || webp)
info: true, //图片大小信息
canScale: true, //图片是否允许滚轮缩放
autoCrop: false, //是否默认生成截图框
autoCropWidth: 100, //默认生成截图框宽度
autoCropHeight: 100, //默认生成截图框高度
fixed: false, //是否开启截图框宽高固定比例
fixedNumber: [1.53, 1], //截图框的宽高比例
full: false, //false按原比例裁切图片,不失真
fixedBox: false, //固定截图框大小,不允许改变
canMove: true, //上传图片是否可以移动
canMoveBox: true, //截图框能否拖动
original: false, //上传图片按照原始比例渲染
centerBox: false, //截图框是否被限制在图片里面
height: true, //是否按照设备的dpr 输出等比例图片
infoTrue: true, //true为展示真实输出图片宽高,false展示看到的截图框宽高
maxImgSize: 3000, //限制图片最大宽度和高度
enlarge: 1, //图片根据截图框输出比例倍数
mode: '500px 400px' //图片默认渲染方式
}
};
},
methods: {
//初始化函数
imgLoad (msg) {
console.log("工具初始化函数",msg)
},
//图片缩放
changeScale (num) {
num = num || 1
this.$refs.cropper.changeScale(num)
},
//向左旋转
rotateLeft () {
this.$refs.cropper.rotateLeft()
},
//向右旋转
rotateRight () {
this.$refs.cropper.rotateRight()
},
//实时预览函数
realTime (data) {
this.previews = data
},
//选择图片
selectImg (e) {
let file = e.target.files[0]
this.fileName = file.name;
if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
this.$message({
message: '图片类型要求:jpeg、jpg、png',
type: "error"
});
return false
}
let reader = new FileReader()
//读取为base64
reader.readAsDataURL(file)
// 读取操作完成触发
reader.onload = (e) => {
let data;
if (typeof e.target.result === 'object') {
// 把Array Buffer转化为blob 如果是base64不需要
data = window.URL.createObjectURL(new Blob([e.target.result])) // 转化为url
} else {
data = e.target.result;
}
// 因为调用了readAsDataURL方法规定将文件读取为base64,所以data为当前选择文件的base64形式
this.option.img = data;
}
},
// 开始截图
cropImageStart() {
this.$refs.cropper.startCrop()
this.option.autoCrop = true;
},
// 停止截图
cropImageStop() {
this.$refs.cropper.stopCrop()
this.option.autoCrop = false;
},
// 清除截图
cropImageClear() {
this.$refs.cropper.clearCrop()
this.option.autoCrop = false;
},
//上传图片
uploadImg (type) {
let _this = this;
if (type === 'blob') {
//获取截图的blob数据
this.$refs.cropper.getCropBlob(async (data) => {
let formData = new FormData();
// 注意: 如果你指定一个 Blob 作为数据添加到 FormData 对象中,
// 文件名会被放在 "Content-Disposition" 头部(常常会根据浏览器变化而变化)传给服务器。
formData.append('file',data,this.fileName)
// 调用axios上传
let res = await upload.getAddress(formData)
if(res.code === 200){
console.log(res)
}
})
}
},
// 下载图片
downloadImage(type) {
if(type == 'blob') {
this.$refs.cropper.getCropBlob(async (data) => {
let url = window.URL.createObjectURL(data); // 生成data的URl
var aLink = document.createElement('a')
aLink.download = this.fileName;
aLink.href = url;
aLink.click();
window.URL.revokeObjectURL(data) // 释放创建的URL对象
})
}
},
},
}
</script>
以上就是基本操作了,详细信息还是看官方文档吧。