vue图片裁剪vue-cropper

609 阅读5分钟

移动端vue3中使用vue-cropper(Vue2也可以)

一、安装使用

1. 安装

# npm 安装
npm install vue-cropper
npm install vue-cropper@next

2. 使用

<!-- template -->
<div class="cropper" >
       <!-- ...参考为参考文档 -->
       <VueCropper ref="cropper" ... />
</div>
// script
import { VueCropper } from "vue-cropper";
/* style */
.cropper{
  width: 100vw;
  height: calc(100vh - 370px);
}
/*  */
.vue-cropper[data-v-26736c2c] {
  position: relative;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  direction: ltr;
  touch-action: none;
  text-align: left;
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC)
}

.cropper-box[data-v-26736c2c],
.cropper-box-canvas[data-v-26736c2c],
.cropper-drag-box[data-v-26736c2c],
.cropper-crop-box[data-v-26736c2c],
.cropper-face[data-v-26736c2c] {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  user-select: none
}

.cropper-box-canvas img[data-v-26736c2c] {
  position: relative;
  text-align: left;
  user-select: none;
  transform: none;
  max-width: none;
  max-height: none
}

.cropper-box[data-v-26736c2c] {
  overflow: hidden
}

.cropper-move[data-v-26736c2c] {
  cursor: move
}

.cropper-crop[data-v-26736c2c] {
  cursor: crosshair
}

.cropper-modal[data-v-26736c2c] {
  background: rgba(0, 0, 0, .5)
}

.cropper-view-box[data-v-26736c2c] {
  display: block;
  overflow: hidden;
  width: 100%;
  height: 100%;
  outline: 1px solid #39f;
  outline-color: #3399ffbf;
  user-select: none
}

.cropper-view-box img[data-v-26736c2c] {
  user-select: none;
  text-align: left;
  max-width: none;
  max-height: none
}

.cropper-face[data-v-26736c2c] {
  top: 0;
  left: 0;
  background-color: #fff;
  opacity: .1
}

.crop-info[data-v-26736c2c] {
  position: absolute;
  left: 0px;
  min-width: 65px;
  text-align: center;
  color: #fff;
  line-height: 20px;
  background-color: #000c;
  font-size: 12px
}

.crop-line[data-v-26736c2c] {
  position: absolute;
  display: block;
  width: 100%;
  height: 100%;
  opacity: .1
}

.line-w[data-v-26736c2c] {
  top: -3px;
  left: 0;
  height: 5px;
  cursor: n-resize
}

.line-a[data-v-26736c2c] {
  top: 0;
  left: -3px;
  width: 5px;
  cursor: w-resize
}

.line-s[data-v-26736c2c] {
  bottom: -3px;
  left: 0;
  height: 5px;
  cursor: s-resize
}

.line-d[data-v-26736c2c] {
  top: 0;
  right: -3px;
  width: 5px;
  cursor: e-resize
}

.crop-point[data-v-26736c2c] {
  position: absolute;
  width: 8px;
  height: 8px;
  opacity: .75;
  background-color: #39f;
  border-radius: 100%
}

.point1[data-v-26736c2c] {
  top: -4px;
  left: -4px;
  cursor: nw-resize
}

.point2[data-v-26736c2c] {
  top: -5px;
  left: 50%;
  margin-left: -3px;
  cursor: n-resize
}

.point3[data-v-26736c2c] {
  top: -4px;
  right: -4px;
  cursor: ne-resize
}

.point4[data-v-26736c2c] {
  top: 50%;
  left: -4px;
  margin-top: -3px;
  cursor: w-resize
}

.point5[data-v-26736c2c] {
  top: 50%;
  right: -4px;
  margin-top: -3px;
  cursor: e-resize
}

.point6[data-v-26736c2c] {
  bottom: -5px;
  left: -4px;
  cursor: sw-resize
}

.point7[data-v-26736c2c] {
  bottom: -5px;
  left: 50%;
  margin-left: -3px;
  cursor: s-resize
}

.point8[data-v-26736c2c] {
  bottom: -5px;
  right: -4px;
  cursor: se-resize
}

@media screen and (max-width: 500px) {
  .crop-point[data-v-26736c2c] {
    position: absolute;
    width: 20px;
    height: 20px;
    opacity: .45;
    background-color: #39f;
    border-radius: 100%
  }

  .point1[data-v-26736c2c] {
    top: -10px;
    left: -10px
  }

  .point2[data-v-26736c2c],
  .point4[data-v-26736c2c],
  .point5[data-v-26736c2c],
  .point7[data-v-26736c2c] {
    display: none
  }

  .point3[data-v-26736c2c] {
    top: -10px;
    right: -10px
  }

  .point4[data-v-26736c2c] {
    top: 0;
    left: 0
  }

  .point6[data-v-26736c2c] {
    bottom: -10px;
    left: -10px
  }

  .point8[data-v-26736c2c] {
    bottom: -10px;
    right: -10px
  }
}

二、文档

1. props

名称功能默认值可选值
img裁剪图片的地址url 地址, base64, blob
outputSize裁剪生成图片的质量10.1 ~ 1
outputType裁剪生成图片的格式jpg (jpg 需要传入jpeg)jpeg, png, webp
info裁剪框的大小信息truetrue, false
canScale图片是否允许滚轮缩放truetrue, false
autoCrop是否默认生成截图框falsetrue, false
autoCropWidth默认生成截图框宽度容器的 80%0 ~ max
autoCropHeight默认生成截图框高度容器的 80%0 ~ max
fixed是否开启截图框宽高固定比例truetrue, false
fixedNumber截图框的宽高比例[1, 1][ 宽度 , 高度 ]
full是否输出原图比例的截图falsetrue, false
fixedBox固定截图框大小不允许改变falsetrue, false
canMove上传图片是否可以移动truetrue, false
canMoveBox截图框能否拖动truetrue, false
original上传图片按照原始比例渲染falsetrue, false
centerBox截图框是否被限制在图片里面falsetrue, false
high是否按照设备的dpr 输出等比例图片truetrue, false
infoTruetrue 为展示真实输出图片宽高 false 展示看到的截图框宽高falsetrue, false
maxImgSize限制图片最大宽度和高度20000 ~ max
enlarge图片根据截图框输出比例倍数10 ~ max(建议不要太大不然会卡死的呢)
mode图片默认渲染方式containcontain , cover, 100px, 100% auto

2. 可用回调方法

  • @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 // 右下角
   }
 }

2. 内置方法 和 属性

通过 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)  
    //   blob转 file
  var result = new File([data], '文件名', { type: data.type, lastModified: Date.now() });
  console.log(result)
})