当前位置: 首页 > article >正文

vue中 通过cropperjs 实现图片裁剪

cropperjs 官方文档: https://www.npmjs.com/package/cropperjs

最终效果图

在这里插入图片描述

具体实现

  1. 安装 cropperjs
npm install cropperjs --save
  1. 引入 cropperjs
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'
  1. 自定义 裁剪图片弹窗 组件
<template>
  <el-dialog title="图片裁剪" :visible.sync="dialogVisible" width="1300px" :append-to-body="true">
    <div class="cropper-content">
      <!-- 剪裁框 -->
      <div class="cropper">
        <img ref="image" :src="imgFile" alt="">
      </div>
      <!-- 预览框 -->
      <div
        class="show-preview"
        :style="{
          overflow: 'hidden',
          margin: '0 25px',
          display: 'flex',
          'align-items': 'center'
        }"
      >
        <div class="preview before" />
      </div>
    </div>
    <div class="footer-btn">
      <!-- 缩放旋转按钮 -->
      <div class="scope-btn">
        <el-tooltip class="item" effect="dark" content="放大" placement="top">
          <el-button icon="el-icon-zoom-in" @click="cropperzoom(0.05)" />
        </el-tooltip>
        <el-tooltip class="item" effect="dark" content="缩小" placement="top">
          <el-button icon="el-icon-zoom-out" @click="cropperzoom(-0.05)" />
        </el-tooltip>
        <el-tooltip
          class="item"
          effect="dark"
          content="逆时针旋转"
          placement="top"
        >
          <el-button
            icon="el-icon-refresh-left"
            @click="cropperRotate(-90)"
          />
        </el-tooltip>
        <el-tooltip
          class="item"
          effect="dark"
          content="顺时针旋转"
          placement="top"
        >
          <el-button
            icon="el-icon-refresh-right"
            @click="cropperRotate(90)"
          />
        </el-tooltip>
      </div>
      <div class="upload-btn">
        <el-button class="btn" @click="closeCropper">取消</el-button>
        <el-button
          type="primary"
          @click="sureSave()"
        >确定</el-button>
      </div>
    </div>
  </el-dialog>
</template>

<script>
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'

export default {
  props: {
    imgFile: {
      type: String,
      default: ''
    },
    visible: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      myCropper: null,
      afterImg: ''
    }
  },
  computed: {
    dialogVisible: {
      get() {
        return this.visible
      },
      set(val) {
        this.$emit('update:visible', val)
      }
    }
  },
  watch: {
    imgFile(val) {
      if (val) {
        setTimeout(() => {
          if (this.myCropper) {
          	// 这里很重要,不然弹窗再次弹出后图片不会更新
            this.myCropper.destroy()
            this.init()
          } else {
            this.init()
          }
        })
      }
    },
    visible: {
      handler: function (val) {
        if (!val) {
          this.myCropper.destroy()
        }
      }
    }
  },
  methods: {
    closeCropper() {
      this.$emit('closeCropper')
    },
    init() {
      this.myCropper = new Cropper(this.$refs.image, {
        viewMode: 1,
        dragMode: 'move',
        preview: '.before',
        background: false,
        autoCropArea: 0.8,
        zoomOnWheel: true
      })
    },
    sureSave() {
      this.afterImg = this.myCropper
        .getCroppedCanvas({
          imageSmoothingQuality: 'high'
        })
        .toDataURL('image/jpeg')
      this.$emit('cropperImg', this.base64ToBlob(this.afterImg))
    },
    base64ToBlob(code) {
      const parts = code.split(';base64,')
      const contentType = parts[0].split(':')[1]
      const raw = window.atob(parts[1])
      const rawLength = raw.length

      const uInt8Array = new Uint8Array(rawLength)

      for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i)
      }
      return new Blob([uInt8Array], {
        type: contentType
      })
    },
    // 缩放
    cropperzoom(val) {
      this.myCropper.zoom(val)
    },
    // 旋转
    cropperRotate(val) {
      this.myCropper.rotate(val)
    }
  }
}
</script>
  <style lang="scss" scoped>
  .cropper {
    border: 1px solid #fff;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMzTjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC);
    img{
      width: 100%;
      opacity: 0;
    }
  }
  .cropper-content {
    display: flex;
    display: -webkit-flex;
    justify-content: flex-end;
    -webkit-justify-content: flex-end;
  }
  .cropper-content .cropper {
    // width: 550px;
    // height: 400px;
    width: 600px;
    height: 450px;
    overflow: hidden;
  }
  .cropper-content .show-preview {
    flex: 1;
    -webkit-flex: 1;
    display: flex;
    display: -webkit-flex;
    justify-content: center;
    -webkit-justify-content: center;
    overflow: hidden;
    /* border: 1px solid #cccccc; */
    background: #cccccc;
    margin-left: 40px;
  }
  .preview {
    overflow: hidden;
    border: 1px solid #468ac8;
    background: #cccccc;
  }
  .footer-btn {
    margin-top: 30px;
    display: flex;
    display: -webkit-flex;
    justify-content: flex-end;
    -webkit-justify-content: flex-end;
  }
  .footer-btn .scope-btn {
    width: 260px;
    display: flex;
    display: -webkit-flex;
    justify-content: space-between;
    -webkit-justify-content: space-between;
  }
  .footer-btn .scope-btn span {
    display: inline-block;
    padding: 10px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    background: #fff;
    cursor: pointer;
  }
  .footer-btn .scope-btn span i {
    font-size: 32px;
    color: #333333;
  }
  .footer-btn .upload-btn {
    flex: 1;
    -webkit-flex: 1;
    display: flex;
    display: -webkit-flex;
    justify-content: flex-end;
    -webkit-justify-content: flex-end;
    margin-right: 25px;
    .btn {
        padding: 0 10px;
        height: 29px;
    }
  }
  .solide {
    margin-left: 25px;
    width: 200px;
  }
  .before {
    width: 100%;
    height: 100%;
    overflow: hidden;
  }
  </style>

  1. 使用组件
import cropper from './cropper.vue'

<cropper :imgFile="originBase64" :visible.sync="cropperVisible" v-bind="$attrs" @cropperImg="cropperImg" @closeCropper="closeCropper" v-on="$listeners" />

参考地址:https://www.jianshu.com/p/5f5aafe9e895


http://www.kler.cn/a/394743.html

相关文章:

  • 网络延迟对Python爬虫速度的影响分析
  • JavaSecLab靶场搭建
  • 执行flink sql连接clickhouse库
  • 如何使用 Web Scraper API 高效采集 Facebook 用户帖子信息
  • 如何使用ffmpeg命令行进行录屏
  • 性能测试|JMeter接口与性能测试项目
  • 开源项目低代码表单设计器FcDesigner扩展右侧组件的配置规则
  • Spring Cloud Gateway(分发请求)
  • 边缘提取函数 [OPENCV--2]
  • 数据结构的时间复杂度和空间复杂度
  • 推荐一款CFD/CAE可视化分析软件:Tecplot 360 EX
  • Unity 中使用 C# 对 Vector2 向量朝向进行顺时针排序及复杂排序场景处理
  • Leetcode 存在重复元素II
  • 深入探索:Scrapy深度爬取策略与实践
  • Linux(文件特殊属性 + FACL 图片+大白话)
  • 机器学习基础04
  • Java项目实战II基于微信小程序的实习记录(开发文档+数据库+源码)
  • Unity3D 制作MMORPG 3D地图编辑器详解
  • FBX福币交易所恒指收跌1.96% 半导体股继续回调
  • SpringBoot整合Freemarker(四)
  • ‘nodemon‘ 不是内部或外部命令,也不是可运行的程序
  • Rollup failed to resolve import “destr“ from ***/node_modules/pinia-plugin-pers
  • Jmeter基础篇(23)TPS和QPS的异同
  • android bootchart安装使用指南
  • PHP Session
  • qt QFrame详解