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使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤

《SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤》本文主要介绍了SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤,文中通过示例代码介绍的非常详... 目录 目标 步骤 1:确保 ProxySQL 和 mysql 主从同步已正确配置ProxySQL 的