Vue学习笔记:vue-cropper实现封装截图组件

本文主要是介绍Vue学习笔记:vue-cropper实现封装截图组件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • vue-cropper一款好用的前端截图插件

项目介绍

使用vue+elementUI写的项目,需要用到图片截图功能视频截图视频直播等功能,关于截图不失真,发现vue-cropper这款插件能满足需求,可以让用户自由调整截图框的宽高、位置,可以根据用户的需求选择截图的格式(png、jpg),也可以选择图片的编码格式(base64、blob)等。

案例展示:

http://zhb_nyx.gitee.io/cropperimg/#/cropperImg

官方网站:

https://github.com/xyxiao001/vue-cropper

组件文档:

图片裁剪 | zhb-ui

第一步:项目中引入vue-cropper插件

npm install vue-cropper --save 或者 npm install vue-cropper -S

第二步:引入依赖,

在main.js中引入

import VueCropper from 'vue-cropper'Vue.use(VueCropper)

按需引入

import VueCropper from 'vue-cropper'

第三步:封装弹框内截图组件

如上图样式布局,

<template><div class="imgCrop-body"><!--图片显示区域--><div class="imgCrop-box"><!--原图--><div class="imgCrop-con"><vue-cropperref="cropper":img="option.img":output-size="option.size":output-type="option.outputType":info="true":full="option.full":fixed="fixed":fixed-number="fixedNumber":can-move="option.canMove":can-move-box="option.canMoveBox":fixed-box="option.fixedBox":original="option.original":auto-crop="option.autoCrop":auto-crop-width="option.autoCropWidth":auto-crop-height="option.autoCropHeight":center-box="option.centerBox"@real-time="realTime":high="option.high"@img-load="imgLoad"mode="cover"></vue-cropper></div><!--截图--><div class="imgCrop-con imgCrop-con-preview" ref="imgCropPreviews"><div class="show-preview" :style="{'width': previews.w + 'px', 'height': previews.h + 'px',  'overflow': 'hidden', 'margin': '5px'}"><div :style="previews.div"><img :src="previews.url" :style="previews.img"></div></div></div></div><!--操作区域--><div class="imgCrop-btn"><div class="ict-query-button"><label for="uploads" style="width:100%;height: 100%; ">上传</label><inputtype="file"id="uploads"style="position:absolute; clip:rect(0 0 0 0);"ref="uploadImg"accept="image/png, image/jpeg, image/gif, image/jpg"@change="uploadImg($event, 1)"></div><div class="ict-query-button"  v-if="!crap"  @click="startCrop">截取</div><div class="ict-query-button"  v-else  @click="stopCropAndSave">保存</div><div class="ict-query-button" @click="changeScale(100)">放大</div><div class="ict-query-button" @click="changeScale(-100)">缩小</div><div class="ict-query-button" @click="clearCrop">清空</div><div class="ict-query-button" @click="refreshCrop">刷新</div><div class="ict-query-button" @click="rotateLeft">向右旋转90度</div><div class="ict-query-button" @click="rotateRight">向左旋转90度</div></div></div><!--到底啦!=======================================================-->
</template>
<script>export default {name: "cropperImgComponents",data(){return {crap: true,previews: {},option: {// 裁剪图片的地址img: '',// 裁剪生成图片的质量size: 1,// 输出原图比例截图 props名fullfull: false,// 裁剪生成图片的格式outputType: 'png',// 上传图片是否可以移动canMove: true,// 固定截图框大小 不允许改变fixedBox: false,// 上传图片按照原始比例渲染original: false,// 截图框能否拖动canMoveBox: true,// 是否默认生成截图框autoCrop: true,// 只有自动截图开启 宽度高度才生效// 默认生成截图框宽度autoCropWidth: 400,// 默认生成截图框高度autoCropHeight: 350,// 截图框是否被限制在图片里面centerBox: false,// 是否按照设备的dpr 输出等比例图片high: true},show: true,// 是否开启截图框宽高固定比例fixed: false,// 截图框的宽高比例fixedNumber: [1, 2],// 裁剪框的大小信息info: true,// canScale 图片是否允许滚轮缩放canScale: true,// infoTrue  true 为展示真实输出图片宽高 false 展示看到的截图框宽高:infoTrue: true,// maxImgSize  限制图片最大宽度和高度maxImgSize: 2000,// enlarge 图片根据截图框输出比例倍数enlarge: 1,// mode  图片默认渲染方式mode: 'contain'}},mounted() {},methods:{setCropImg(){this.$refs.uploadImg.click()this.crap = true},//上传图片uploadImg(e, num) {var file = e.target.files[0]this.file = fileconsole.log(file);if (file.size / 1024 / 1024 > 5) {this.$message.info("上传文件不超过5M");return;}if (!/\.(jpg|png|JPG|PNG)$/.test(file.name)) {this.$message.info('图片类型必须是jpg,png中的一种')return false}var reader = new FileReader()reader.onload = (e) => {let dataif (typeof e.target.result === 'object') {// 把Array Buffer转化为blob 如果是base64不需要data = window.URL.createObjectURL(new Blob([e.target.result]))} else {data = e.target.result}if (num === 1) {this.option.img = data} else if (num === 2) {this.example2.img = data}}// 转化为base64// reader.readAsDataURL(file)// 转化为blobreader.readAsArrayBuffer(file)},imgLoad(msg) {console.log(msg)this.previews.url = msg.url},// 实时预览函数realTime(data) {this.previews = datathis.$emit('', this.previews)console.log(data)},//开始截图startCrop() {this.crap = truethis.$refs.cropper.startCrop()},//停止截图&保存stopCropAndSave() {this.crap = falsethis.$refs.cropper.stopCrop()this.$refs.cropper.getCropData((data) => {this.base64ToFile(data,'cropFile')})},//清空截图clearCrop() {this.$refs.cropper.clearCrop()this.crap = false},//放大缩小changeScale(num) {num = num || 1this.$refs.cropper.changeScale(num)},//刷新refreshCrop() {this.$refs.cropper.refresh()this.crap = false},//向左旋转rotateLeft() {this.$refs.cropper.rotateLeft()},//向右旋转rotateRight() {this.$refs.cropper.rotateRight()},//base64ToFilebase64ToFile(urlData, fileName) {var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1],bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);while(n--){u8arr[n] = bstr.charCodeAt(n);}let imgFile = new File([u8arr], fileName, {type:mime});this.$parent.getCropApi(imgFile,urlData)},}}
</script>
<style lang="scss" scoped>.imgCrop-body{width: 100%;height: 100%;overflow: hidden;//图片显示区域.imgCrop-box{width: 100%;height: calc(100% - 100px);display: flex;justify-content: center;align-items: center;.imgCrop-con{width: calc(50% - 20px);height:  calc(100% - 20px);margin: 10px;&.imgCrop-con-preview{background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMzTjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC");}}}//操作区域.imgCrop-btn{width: 100%;height: 50px;margin-top: 20px;display: flex;justify-content: center;>div{margin: 0 10px;}}}</style>

第四步:封装点击打开文件上传,弹出截取图片

<template><div class="upfile"><div class="addFile" v-if="isAddFile" @click="getCropImg">+</div><div v-else class="addFileImg"  @click="getCropImg"><img   :src="imgBase64"></div><!--截图区域--><div class="CropDialogVisible" v-show="isCropDialogVisible"><div class="CropDialog-main" style="height: 80vh;position: relative;"><div class="CropDialog-close" @click="isCropDialogVisible = false">×</div><cropper-img ref="cropImg"></cropper-img></div></div></div>
</template><script>import cropperImg from './cropperImg.vue'export default {name: "upfile",props: ["type","imgUrl"],created() {console.log(this.imgUrl);if(this.imgUrl){this.imgBase64 = this.imgUrlthis.filedisabled = false}},data() {return {imgBase64:'',//isCropDialogVisible:false,cropFile:'',isAddFile:true};},components:{cropperImg},methods: {getCropImg(){let that = thisthis.$refs.cropImg.setCropImg()setTimeout(function () {that.isCropDialogVisible = true},500)},getCropApi(file,base64){console.log(file, base64);this.imgBase64 = base64this.isCropDialogVisible = falsethis.isAddFile = falsethis.$emit("getCropFile",{File:file,Base64:base64})}}};
</script><style lang="scss" scoped>.CropDialogVisible{width: 100%;height: 100%;position: fixed;top:0;left: 0;background: rgba(0,0,0,.4);display: flex;align-items: center;justify-content: center;z-index: 1000;.CropDialog-main{width: 80%;height: 80%;background: #ffffff;.CropDialog-close{width: 40px;height: 40px;background: #666666;color: #ffffff;display: flex;align-items: center;justify-content: center;border-radius: 50%;position: absolute;top: -12px;right: -20px;font-size: 38px;cursor: pointer;}}}.upfile{width: 200px;.addFileImg{display: block;width: 80px;height: 80px;background: #eeeeee;cursor: pointer;img{display: block;width: 100%;height: 100%;}}.addFile{width: 80px;height: 80px;border: 1px dotted #64686B;border-radius:4px;font-size: 35px;display: flex;align-items: center;justify-content: center;cursor: pointer;color:#64686B;}}.avatar-file {text-align: center;}.avatar-file-text {width: 240px;border: 1px solid #dddddd;border-radius:3px;line-height: 30px;height: 30px;display: flex;align-items: center;justify-content: center;font-weight: 500;font-size: 14px;white-space: nowrap;padding: 0 5px;cursor: pointer;border-radius:0;}.avatar-file-text img {width: 16px;height: 16px;margin-right: 9px;}.avatar-file-imgbox {height: 65px;display: flex;align-items: center;justify-content: flex-start;border: 1px solid#C0C4CC;}.filename {font-size: 14px;font-weight: 400;text-decoration: underline;text-align: left;color: #1d73f6;line-height: 22px;margin-left: 10px;}.filename span {width: 8px;height: 8px;// color: #ff0000;font-size: 36px;cursor: pointer;}
</style>

第五步:调用截取图片组件

<template>
<div style="width: 100%;display: flex;align-items: center;justify-content: center;"><div style="display: flex;align-items: center"><span style="margin-right: 20px;">截取图片</span><cropper-file></cropper-file></div>
</div>
</template><script>import cropperFile from './cropperFile.vue'export default {name: "cropper",data(){},methods:{},components:{cropperFile}}
</script><style scoped></style>

现已将该功能整合进我的UI组件库内,大家可以前往下载使用;

文档如上;

 

最后

热爱分享!乐于助人!

大家好,我是“前端互助会”,欢迎大家关注微信公众号“前端公众号”!

一起学习,共同成长!

这篇关于Vue学习笔记:vue-cropper实现封装截图组件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1099490

相关文章

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

Vue和React受控组件的区别小结

《Vue和React受控组件的区别小结》本文主要介绍了Vue和React受控组件的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录背景React 的实现vue3 的实现写法一:直接修改事件参数写法二:通过ref引用 DOMVu

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja