vue-cropper 一个优雅的图片裁剪插件
一、安装使用
1. 安装
# npm 安装
npm install vue-cropper
# yarn 安装
yarn add vue-cropper
2. 引入
main.js 引入
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
vue 组件引入 VueCropper
import { VueCropper } from 'vue-cropper'
components: {
VueCropper
}
CDN 方式引入
<script src="//cdn.jsdelivr.net/npm/vue-cropper@0.4.9/dist/index.js"></script>
Vue.use(window['vue-cropper'].default)
3. 代码中使用
官方说明:
**重要!**需要关掉本地的 mock 服务, 不然图片转化会报错
**重要!**需要使用外层容器包裹并设置宽高
<div style="width: 200px; height: 200px">
<vue-cropper
ref="cropper"
:img="option.img" // url地址、base64、blob
autoCrop
autoCropWidth="150"
autoCropHeight="150"
centerBox
fixed
:enlarge="option.enlarge"
:canMove="false"
@realTime="realTime"
outputType="png"
/>
</div>
二、文档
1. props
官方说明:目前还不知道什么原因项目里面开启
mock会导致 file 报错,建议使用时关掉mock
| 名称 | 功能 | 默认值 | 可选值 |
|---|---|---|---|
| img | 裁剪图片的地址 | 空 | url 地址, base64, blob |
| outputSize | 裁剪生成图片的质量 | 1 | 0.1 ~ 1 |
| outputType | 裁剪生成图片的格式 | jpg (jpg 需要传入jpeg) | jpeg, png, webp |
| info | 裁剪框的大小信息 | true | true, false |
| canScale | 图片是否允许滚轮缩放 | true | true, false |
| autoCrop | 是否默认生成截图框 | false | true, false |
| autoCropWidth | 默认生成截图框宽度 | 容器的 80% | 0 ~ max |
| autoCropHeight | 默认生成截图框高度 | 容器的 80% | 0 ~ max |
| fixed | 是否开启截图框宽高固定比例 | true | true, false |
| fixedNumber | 截图框的宽高比例 | [1, 1] | [ 宽度 , 高度 ] |
| full | 是否输出原图比例的截图 | false | true, false |
| fixedBox | 固定截图框大小 | 不允许改变 | false |
| canMove | 上传图片是否可以移动 | true | true, false |
| canMoveBox | 截图框能否拖动 | true | true, false |
| original | 上传图片按照原始比例渲染 | false | true, false |
| centerBox | 截图框是否被限制在图片里面 | false | true, false |
| high | 是否按照设备的dpr 输出等比例图片 | true | true, false |
| infoTrue | true 为展示真实输出图片宽高 false 展示看到的截图框宽高 | false | true, false |
| maxImgSize | 限制图片最大宽度和高度 | 2000 | 0 ~ max |
| enlarge | 图片根据截图框输出比例倍数 | 1 | 0 ~ max(建议不要太大不然会卡死) |
| mode | 图片默认渲染方式 | contain | contain , cover, 100px, 100% auto |
2. props 可用回调方法
@realTime实时预览事件@imgMoving图片移动回调函数@cropMoving截图框移动回调函数@imgLoad图片加载的回调, 返回结果success,error
@realTime 实时预览事件
realTime(data) {
var previews = data
var h = 0.5
var w = 0.2
this.previewStyle1 = {
width: previews.w + "px",
height: previews.h + "px",
overflow: "hidden",
margin: "0",
zoom: h
}
this.previewStyle2 = {
width: previews.w + "px",
height: previews.h + "px",
overflow: "hidden",
margin: "0",
zoom: w
}
// 固定为 100 宽度
this.previewStyle3 = {
width: previews.w + "px",
height: previews.h + "px",
overflow: "hidden",
margin: "0",
zoom: 100 / preview.w
}
// 固定为 100 高度
this.previewStyle4 = {
width: previews.w + "px",
height: previews.h + "px",
overflow: "hidden",
margin: "0",
zoom: 100 / preview.h
}
this.previews = data
}
<div class="show-preview" :style="{'width': previews.w + 'px', 'height': previews.h + 'px', 'overflow': 'hidden',
'margin': '5px'}">
<div :style="previews.div">
<img :src="option.img" :style="previews.img">
</div>
</div>
<p>中等大小</p>
<div :style="previewStyle1">
<div :style="previews.div">
<img :src="previews.url" :style="previews.img">
</div>
</div>
<p>迷你大小</p>
<div :style="previewStyle2">
<div :style="previews.div">
<img :src="previews.url" :style="previews.img">
</div>
</div>
@imgMoving 图片移动回调函数
返回的参数内容
{
moving: true, // moving 是否在移动
axis: {
x1: 1, // 左上角
x2: 1,// 右上角
y1: 1,// 左下角
y2: 1 // 右下角
}
}
@cropMoving 截图框移动回调函数
返回的参数内容
{
moving: true, // moving 是否在移动
axis: {
x1: 1, // 左上角
x2: 1,// 右上角
y1: 1,// 左下角
y2: 1 // 右下角
}
}
@imgLoad图片加载回调函数
返回的参数内容
success,error
3. 内置属性与方法
通过 this.$refs.cropper 调用
属性
| 属性 | 说明 |
|---|---|
| this.$refs.cropper.cropW | 截图框宽度 |
| this.$refs.cropper.cropH | 截图框高度 |
方法
| 方法 | 说明 |
|---|---|
| this.$refs.cropper.startCrop() | 开始截图 |
| this.$refs.cropper.stopCrop() | 停止截图 |
| this.$refs.cropper.clearCrop() | 清除截图 |
| this.$refs.cropper.changeScale() | 修改图片大小 正数为变大 负数变小 |
| this.$refs.cropper.getImgAxis() | 获取图片基于容器的坐标点 |
| this.$refs.cropper.getCropAxis() | 获取截图框基于容器的坐标点 |
| this.$refs.cropper.goAutoCrop | 自动生成截图框函数 |
| this.$refs.cropper.rotateRight() | 向右边旋转90度 |
| this.$refs.cropper.rotateLeft() | 向左边旋转90度 |
获取截图内容
-
获取截图的 base64 数据
this.$refs.cropper.getCropData(data => { // do something console.log(data) }) -
获取截图的 blob 数据
this.$refs.cropper.getCropBlob(data => { // do something console.log(data) })
三、实际操作
1. 截图边框可调整,实时预览,生成图片功能
template
<template>
<div>
<!-- 上传图片 -->
<input type="file" accept="image/*" @change="getFileStream($event)">
<!-- 图片截图 -->
<div style="width: 200px; height: 200px">
<vue-cropper
ref="cropper"
:img="option.img"
autoCrop
autoCropWidth="150"
autoCropHeight="150"
centerBox
fixed
:enlarge="option.enlarge"
:canMove="false"
@realTime="realTime"
@imgMoving="imgMoving"
@cropMoving="cropMoving"
@imgLoad="imgLoad"
outputType="png"
/>
</div>
<div>实时预览</div>
<div class="show-preview" :style="previewStyle">
<div :style="previews.div">
<img :src="previews.url" :style="previews.img" />
</div>
</div>
<div>生成图片</div>
<div>
<button @click="getCropData()">获取CropBase64数据</button>
<img :src="base64" alt="base64" />
</div>
</div>
</template>
data
data() {
return {
option: {
img: "https://shnhz.github.io/shn-ui/img/Koala.jpg",
},
previews: {},
previewStyle: {},
base64: "",
enlarge: 1,
};
}
methods
methods: {
// 生成图片
getCropData() {
this.$refs.cropper.getCropData((data) => {
// 输出 base64
// console.log(data);
this.base64 = data;
});
},
// 预览图片
realTime(data) {
this.previews = data;
this.option.enlarge = 200 / this.previews.w
this.previewStyle = {
width: this.previews.w + "px",
height: this.previews.h + "px",
overflow: "hidden",
margin: "0",
// 固定宽度200 截图框若小了则放大内容 大了则缩小内容
zoom: 200 / this.previews.w
};
}
}
预览图使用了 zoom 缩放原理:固定高度或宽度px值 / 变化的宽度或高度
若变化宽/高度越大则为缩小图片内容,边框宽高度固定
若变化宽/高度越小则为放大图片内容,边框宽高度固定
2. 截图边框固定,图片可调整,实时预览,生成图片功能
template、data、methods与实际操作 1 中一致,只需更改属性canMoveBox 与 fixedBox
使用组件自带属性props:canMoveBox [截图框能否拖动]、fixedBox [固定截图框大小]
设置 :canMoveBox="false" 在截图框后的图片可以拖拉缩放
设置 fixedBox 为 true 固定截图框大小
PS:可以添加截图边框样式以及其他样式
style
// 设置截图边框为⚪
<style scoped>
/deep/.cropper-view-box{
border-radius: 50%;
}
/deep/.cropper-face{
border-radius: 50%;
}
</style>
3. 结果
操作 1 中实现结果:
操作 2 中实现结果:
四、最后
简单实现了上传图片文件至截图框内,实现如下:
使用 input 标签,设置 type=“file” 接收 accept 为图像,并设置了 change 事件
template
<!-- 上传图片 -->
<input type="file" accept="image/*" @change="getFileStream($event)">
methods
// 获取文件流
getFileStream(e){
this.fileToImg(e.target.files[0])
},
// 上传文件转换成 image base64格式
fileToImg(file) {
var reader = new FileReader()
// 读取操作成功完成触发
reader.onload = (e) =>{
// 将 vue-cropper 中 img 属性值设置为上传文件数据
this.option.img = e.target.result
}
// 将文件读取后返回URL(base64)
reader.readAsDataURL(file)
}