图片裁剪功能

图片裁剪

安装cropperjs插件 (下面有cropperjs使用文档)

yarn add cropperjs

上传图片按钮

   <!-- 上传图片按钮 -->
    <div class="btn-item" @click="uploadImg">上传图片</div>
     <input type="file" hiddenref="uploadImg" name="file" accept="image/*" @change="fileChange" />
        
    <!-- 使用图片裁剪组件 -->   
      <previewImageLayer
      v-if="showPreviewImageLayer"
      :imgSrc="imgSrc"
      @newImgUrl="newImgUrl"
      :showPreviewImageLayer.sync="showPreviewImageLayer"
     ></previewImageLayer>    
         
          
     uploadImg() {
      this.$refs.uploadImg.click();
    },
    
    fileChange(event) {
      //读取上传文件
      let reader = new FileReader();
      if (event.target.files[0]) {
        //readAsDataURL方法可以将File对象转化为data:URL格式的字符串(base64编码)
        reader.readAsDataURL(event.target.files[0]);
        reader.onload = (e) => {
          console.log(e, "e");
          let dataURL = reader.result;
          //将img的src改为刚上传的文件的转换格式
          this.imgSrc = dataURL;
          this.showPreviewImageLayer = true;
        };
      }
    }, 
    //裁剪后的图片
    newImgUrl(val) {
      this.imgSrc = val;
    },

封装图片裁剪组件

参数描述
imgSrc父组件传过来的图片地址
cropperImgUrl裁剪完成的图片的地址
newImgUrl裁剪完成的图片(子传父)
<template>
  <div class="maskLayer" v-if="showPreviewImageLayer">
    <div class="saveItemLayer dialogCon">
      <div class="dcTitle">
        <p class="title">编辑图片</p>
        <p class="close" v-on:click="handleCloseLayer">
          <i class="el-icon-close"></i>
        </p>
      </div>
      <div class="silCon">
        <div class="img">
          <img id="cropImg" :src="imgSrc" />
        </div>
        <!-- 两个用于预览的div  -->
        <div class="wrap">
          <div class="previewText">裁剪预览</div>
          <div class="previewBox"></div>
          <div class="previewBoxRound"></div>
        </div>
      </div>
      <canvas id="toCanvas" ref="toCanvas"></canvas>
      <div class="dcBottom">
       <!-- 自己配置功能  -->
        <p class="item" @click="rotate">旋转</p>
        <p class="input" style="width:240px">
          <span>缩放倍数<span style="color:#f00;font-size: 12px;">(正数放大,负数缩小,可以为小数)</span></span
          ><el-input v-model="zoomVal" placeholder="输入缩放倍数"></el-input>
        </p>
        <p class="item" @click="zoom">缩放</p>
        <p class="item" @click="reset">重置</p>
        <p class="item" v-on:click="handleSaveItem">确定</p>
        <p class="item" v-on:click="handleCloseLayer">取消</p>
      </div>
    </div>
  </div>
</template> 
  
  <script>
//引入Cropper.js
import "cropperjs/dist/cropper.css";
import Cropper from "cropperjs";
export default {
  data() {
    return {
      radio: 0,
      CROPPER: null,
      zoomVal: 0.1,
      cropperImgUrl:''
    };
  },
  props: {
    imgSrc: {
      type: String,
      default: null,
    },
    showPreviewImageLayer: {
      type: Boolean,
      default: false,
    },
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      const image = document.getElementById("cropImg");
      //创建cropper实例
      this.CROPPER = new Cropper(image, {
        aspectRatio: 16 / 16,
        viewMode: 0,
        minContainerWidth: 600,
        minContainerHeight: 600,
        dragMode: "move",
        preview: [
          document.querySelector(".previewBox"),
          document.querySelector(".previewBoxRound"),
        ],
      });
    },
    handleSaveItem() {
      //getCroppedCanvas方法可以将裁剪区域的数据转换成canvas数据
      this.CROPPER.getCroppedCanvas({
        maxWidth: 4096,
        maxHeight: 4096,
        fillColor: "#fff",
        imageSmoothingEnabled: true,
        imageSmoothingQuality: "high",
      }).toBlob((blob) => {
        //使用 URL.createObjectURL() 方法将blob转化为一个 URL
        this.cropperImgUrl = URL.createObjectURL(blob);
        this.$emit('newImgUrl',this.cropperImgUrl)
        this.$emit("update:showPreviewImageLayer", false);
      });
    },
    rotate() {
      this.CROPPER.rotate(90);
    },
    zoom() {
      this.CROPPER.zoom(this.zoomVal);
    },
    reset() {
      this.CROPPER.reset();
    },
    handleCloseLayer() {
      this.$emit("update:showPreviewImageLayer", false);
    },
  },
  created() {},
};
</script>
  <style lang="scss" scoped>
.maskLayer {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  position: fixed;
  left: 0;
  top: 0;
  z-index: 999;
  .dialogCon {
    width: 1200px;
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    background-color: #fff;
    border-radius: 6px 6px 0px 0px;
    padding-bottom: 80px;

    .dcTitle {
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;
      height: 49px;
      color: #214361;
      border-bottom: 1px solid rgba(149, 161, 184, 0.2);
      border-radius: 6px 6px 0px 0px;

      .title {
        font-size: 20px;
        font-weight: bold;
        color: #214361;
        margin-left: 15px;
      }

      .close {
        margin-right: 30px;
        cursor: pointer;
        i {
          font-size: 16px;
        }
      }
    }
    .silCon {
      width: 100%;
      height: 660px;
      padding-top: 40px;
      padding-left: 27px;
      padding-bottom: 40px;
      display: flex;
      align-items: center;
      .img {
        flex: 1;
        height: 100%;
        margin-right: 20px;
        img {
          width: 100%;
          height: 100%;
        }
      }
      .wrap {
        width: 200px;
        .previewBox,
        .previewBoxRound {
          box-shadow: 0 0 5px #adadad;
          width: 150px;
          height: 150px;
          margin-top: 30px;
          overflow: hidden; /*这个超出设置为隐藏很重要,否则就会整个显示出来了*/
        }
        .previewBoxRound {
          border-radius: 50%; /*设置为圆形*/
        }
      }
    }
    .dcBottom {
      position: absolute;
      left: 0;
      bottom: 0;
      display: flex;
      justify-content: end;
      align-items: center;
      width: 100%;
      height: 60px;
      background: #fafafa;
      border-top: 1px solid rgba(149, 161, 184, 0.2);
      margin-bottom: 0;
      .input {
        display: flex;
        flex-direction: column;
        width: 200px;
        margin-left: 10px;
        margin-right: 10px;
      }
      .item {
        width: 80px;
        height: 30px;
        color: #fff;
        font-size: 14px;
        line-height: 30px;
        text-align: center;
        background: #38c8c0;
        cursor: pointer;
        &:nth-child(1) {
          margin-right: 10px;
        }

        &:last-child {
          margin-right: 20px;
          color: #214361;
          background: #fafafa;
          border: 1px solid #dee4e9;
        }
      }
    }
  }
}
</style>

cropperjs使用文档

import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'
this.myCropper = new Cropper('被裁剪对象', '配置对象') //返回一个cropper对象

//用法
this.myCropper.zoom(0.1) //(正数放大,负数缩小,可以为小数)单位为数字,0.1为在原缩放基础上增加0.1倍
this.myCropper.rotate(90) //旋转图片,单位为数字,90为顺时针旋转90度
  1. 配置对象

    viewMode 视图控制

    • 0 无限制
    • 1 限制裁剪框不能超出图片的范围
    • 2 限制裁剪框不能超出图片的范围 且图片填充模式为 cover 最长边填充
    • 3 限制裁剪框不能超出图片的范围 且图片填充模式为 contain 最短边填充

    dragMode 拖拽图片模式

    • crop 形成新的裁剪框
    • move 图片可移动
    • none 什么也没有

    initialAspectRatio 裁剪框宽高比的初始值 默认与图片宽高比相同 只有在aspectRatio没有设置的情况下可用

    aspectRatio 设置裁剪框为固定的宽高比

    data 之前存储的裁剪后的数据 在初始化时会自动设置 只有在autoCrop设置为true时可用

    preview 预览 设置一个区域容器预览裁剪后的结果

    • Element, Array (elements), NodeList or String (selector)

    responsive 在窗口尺寸调整后 进行响应式的重渲染 默认true

    restore 在窗口尺寸调整后 恢复被裁剪的区域 默认true

    checkCrossOrigin 检查图片是否跨域 默认true 如果是 会在被复制的图片元素上加上属性crossOrigin 并且在src上加上一个时间戳 避免重加载图片时因为浏览器缓存而加载错误

    checkOrientation 检查图片的方向信息(仅JPEG图片有)默认true 在旋转图片时会对图片方向值做一些处理 以解决IOS设备上的一些问题

    modal 是否显示图片和裁剪框之间的黑色蒙版 默认true

    guides 是否显示裁剪框的虚线 默认true

    center 是否显示裁剪框中间的 ‘+’ 指示器 默认true

    highlight 是否显示裁剪框上面的白色蒙版 (很淡)默认true

    background 是否在容器内显示网格状的背景 默认true

    autoCrop 允许初始化时自动的裁剪图片 配合 data 使用 默认true

    autoCropArea 设置裁剪区域占图片的大小 值为 0-1 默认 0.8 表示 80%的区域

    movable 是否可以移动图片 默认true

    rotatable 是否可以旋转图片 默认true

    scalable 是否可以缩放图片(可以改变长宽) 默认true

    zoomable 是否可以缩放图片(改变焦距) 默认true

    zoomOnTouch 是否可以通过拖拽触摸缩放图片 默认true

    zoomOnWheel 是否可以通过鼠标滚轮缩放图片 默认true

    wheelZoomRatio 设置鼠标滚轮缩放的灵敏度 默认 0.1

    cropBoxMovable 是否可以拖拽裁剪框 默认true

    cropBoxResizable 是否可以改变裁剪框的尺寸 默认true

    toggleDragModeOnDblclick 是否可以通过双击切换拖拽图片模式(move和crop)默认true 当拖拽图片模式为none时不可切换 该设置必须浏览器支持双击事件

    minContainerWidth(200)、minContainerHeight(100)、minCanvasWidth(0)、minCanvasHeight(0)、minCropBoxWidth(0)、minCropBoxHeight(0) 容器、图片、裁剪框的 最小宽高 括号内为默认值 注意 裁剪框的最小高宽是相对与页面而言的 并非相对图片

    方法使用

    crop() 手动显示裁剪框

    reset() 重置图片和裁剪框为初始状态

    replace(url[, hasSameSize]) 替换图片路径并且重建裁剪框

    • url 新路径
    • hasSameSize 默认值false 设置为true表示新老图片尺寸一样 只需要更换路径无需重建裁剪框

    enable() 解冻 裁剪框

    disable() 冻结 裁剪框

    destroy() 摧毁裁剪框并且移除cropper实例

    move(offsetX[, offsetY]) 移动图片指定距离 一个参数代表横纵向移动距离一样

    moveTo(x[, y]) 移动图片到一个指定的点 一个参数代表横纵向移动距离一样

    zoom(ratio) 缩放 ratio大于零是放大 小于零缩小

    zoomTo(ratio[, pivot]) 缩放并设置中心点的位置

    rotate(degree) 旋转 类似css

    rotateTo(degree) 旋转到绝对角度

    scale(scaleX[, scaleY])、scaleX(scaleX)、scaleY(scaleY) 缩放 一个参数代表横纵向缩放值一样

    getData([rounded]) 返回裁剪区域基于原图片!原尺寸!的位置和尺寸 rounded默认为false 表示是否显示四舍五入后的数据 有了这些数据可以直接在原图上进行裁剪显示

    setData(data) 改变裁剪区域基于原图的位置和尺寸 仅当viewMode 不为0时有效

    getContainerData()、getImageData()、getCanvasData()、setCanvasData(data)、getCropBoxData()、setCropBoxData(data) 容器、图片容器(画布)、图片、裁剪区域相对容器的数据设置和获取

    getCroppedCanvas([options]) 得到被裁剪图片的一个canvas对象 options设置这个canvas的一些数据

    • width、height、minWidth、minHeight、maxWidth、maxHeight、fillColor、imageSmoothingEnabled(图片是否是光滑的 默认true)、imageSmoothingQuality(图片的质量 默认low 还有medium、high)

    setAspectRatio(aspectRatio) 改变裁剪区域的宽高比

    setDragMode([mode]) 设置拖拽图片模式

    事件

    ready 渲染前(图片已经被加载、cropper实例已经准备完毕)的准备工作事件

    cropstart、cropmove、cropend、crop 开始画裁剪框(或画布)、画裁剪框(或画布)的中途、裁剪框(或画布)画完、进行裁剪事件 event.detail.originalEvent、event.detail.action

    • 当autoCrop为true crop事件会在ready之前触发

    zoom 裁剪框缩放事件

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值