cropperjs 裁剪/框选图片
1.效果
2.使用组件
<!-- 父级 --><Cropper ref="cropperRef" :imgUrl="url" @searchImg="searchImg"></Cropper>
3.封装组件
<template><el-dialog :title="title" :visible.sync="dialogVisible" width="1000px"><input ref="input" type="file" name="image" @change="setImage" /><div class="flex justify-around"><div class="w-480px h-270px flex justify-center items-center"><divv-show="!imgSrc"@click="showFileChooser"class="w-full h-full flex cursor-pointer justify-center items-center border-1px border-dashed border-gray-300 rounded-lg"><i class="font-size-20px el-icon-plus avatar-uploader-icon"></i></div><!-- :aspect-ratio="16 / 16" --><vue-cropperv-show="imgSrc"class="w-full h-full"ref="cropper":src="imgSrc"alt="Source Image"@ready="ready"@cropstart="cropstart"@cropmove="cropmove"@cropend="cropend"@crop="crop"@zoom="zoom"preview=".preview":autoCropArea="autoCropArea"></vue-cropper></div><div class="w-420px"><div class="font-bold color-#666 ml-20px mb-10px">预览</div><div v-show="!imgSrc" class="preview_empty ml-20px"></div><div v-show="imgSrc" class="preview ml-20px"></div><!-- <div>裁剪图片</div><div class="cropped-image"><el-image class="h-180px" v-if="cropImg" :src="cropImg" alt="Cropped Image" /><div v-else class="crop-placeholder" /></div> --><div class="actions mt-10px ml-10px"><el-button class="mb-10px ml-10px" type="primary" @click="zoom(0.2)" size="small">放大</el-button><el-button class="mb-10px" type="primary" @click="zoom(-0.2)" size="small">缩小</el-button><el-button class="mb-10px" type="primary" @click="move(-10, 0)" size="small">左移</el-button><el-button class="mb-10px" type="primary" @click="move(10, 0)" size="small">右移</el-button><el-button class="mb-10px" type="primary" @click="move(0, -10)" size="small">上移</el-button><el-button class="mb-10px" type="primary" @click="move(0, 10)" size="small">下移</el-button><el-button class="mb-10px" type="primary" @click="rotate(90)" size="small">旋转90°</el-button><el-button class="mb-10px" type="primary" @click="rotate(-90)" size="small">旋转-90°</el-button><!-- <el-button class="mb-10px" type="primary" @click="flipX" size="small">水平翻转</el-button><el-button class="mb-10px" type="primary" @click="flipY" size="small">垂直翻转</el-button> --><!-- <el-button class="mb-10px" type="success" @click="cropImage" size="small">搜索</el-button> --><el-button class="mb-10px" type="primary" @click="reset" size="small" plain>重置</el-button><el-buttonv-if="!isHideFileChooser"class="mb-10px"type="success"@click="showFileChooser"size="small"plain>更换图片</el-button><!-- <el-button class="mb-10px" type="primary" @click="getCropBoxData" size="small">获取裁剪框数据</el-button><el-button class="mb-10px" type="primary" @click="setCropBoxData" size="small">设置裁剪框数据</el-button><el-button class="mb-10px" type="primary" @click="getData" size="small">获取裁剪数据</el-button><el-button class="mb-10px" type="primary" @click="setData" size="small">设置裁剪数据</el-button> --></div></div></div><span slot="footer" class="dialog-footer"><el-button size="small" @click="dialogVisible = false">取 消</el-button><el-button size="small" type="primary" @click="cropImage">搜索</el-button></span></el-dialog>
</template><script>
import VueCropper from 'vue-cropperjs'
import 'cropperjs/dist/cropper.css'export default {name: 'Cropper',components: { VueCropper },props: {title: {type: String,default: '图片框选'},imgUrl: {type: String,default: ''},autoCropArea: {type: Number,default: 0.6},isHideFileChooser: {type: Boolean,default: true}},data() {return {imgSrc: '',dialogVisible: false,cropImg: ''}},watch: {imgUrl(val) {if (val) {this.imgSrc = valconsole.log('🚀 ~ imgUrl ~ this.imgSrc:', this.imgSrc)}}},methods: {open() {if (!this.imgUrl) {this.imgSrc = ''}this.dialogVisible = true},handleClose() {this.$emit('close')},ready() {// console.log('🚀 ~ ready ~ this.$refs.cropper:', this.$refs.cropper)},cropImage() {// get image data for post processing, e.g. upload or setting image srcthis.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL()const base64Data = this.cropImg.split(',')[1]this.$emit('searchImg', base64Data)this.dialogVisible = false},cropstart() {// console.log('🚀 ~ cropstart ~')},cropmove() {// console.log('🚀 ~ cropmove ~')},cropend() {// console.log('🚀 ~ cropend ~')},crop(data) {// console.log('🚀 ~ crop ~ data:', data)},flipX() {const dom = this.$refs.flipXlet scale = dom.getAttribute('data-scale')scale = scale ? -scale : -1this.$refs.cropper.scaleX(scale)dom.setAttribute('data-scale', scale)},flipY() {const dom = this.$refs.flipYlet scale = dom.getAttribute('data-scale')scale = scale ? -scale : -1this.$refs.cropper.scaleY(scale)dom.setAttribute('data-scale', scale)},getCropBoxData() {this.data = JSON.stringify(this.$refs.cropper.getCropBoxData(), null, 4)},getData() {this.data = JSON.stringify(this.$refs.cropper.getData(), null, 4)console.log('🚀 ~ getData ~ this.data:', this.data)},move(offsetX, offsetY) {this.$refs.cropper.move(offsetX, offsetY)},reset() {this.$refs.cropper.reset()},rotate(deg) {this.$refs.cropper.rotate(deg)},setCropBoxData() {if (!this.data) returnthis.$refs.cropper.setCropBoxData(JSON.parse(this.data))},setData() {if (!this.data) returnthis.$refs.cropper.setData(JSON.parse(this.data))},setImage(e) {const file = e.target.files[0]if (file.type.indexOf('image/') === -1) {alert('Please select an image file')return}if (typeof FileReader === 'function') {const reader = new FileReader()reader.onload = (event) => {this.imgSrc = event.target.result// rebuild cropperjs with the updated sourcethis.$refs.cropper.replace(event.target.result)}reader.readAsDataURL(file)} else {alert('Sorry, FileReader API not supported')}},showFileChooser() {this.$refs.input.click()},zoom(percent) {this.$refs.cropper.relativeZoom(percent)}},mounted() {this.imgSrc = this.imgUrl}
}
</script><style lang="scss" scoped>
input[type='file'] {display: none;
}.preview-area {width: 100%;
}.preview-area p {font-size: 1.25rem;margin: 0;margin-bottom: 1rem;
}.preview-area p:last-of-type {margin-top: 1rem;
}.preview {width: 270px;height: calc(270px * (9 / 16));overflow: hidden;background-color: #f5f5f5;
}.preview_empty {width: 270px;height: calc(270px * (9 / 16));overflow: hidden;background-color: #f5f5f5;
}
.crop-placeholder {width: 100%;height: 200px;background: #ccc;
}.cropped-image img {max-width: 100%;
}
</style>
相关文章:

cropperjs 裁剪/框选图片
1.效果 2.使用组件 <!-- 父级 --><Cropper ref"cropperRef" :imgUrl"url" searchImg"searchImg"></Cropper>3.封装组件 <template><el-dialog :title"title" :visible.sync"dialogVisible" wi…...
ArkTS开发系列之事件(2.8.2手势事件)
上篇回顾:ArkTS开发系列之事件(2.8.1触屏、键鼠、焦点事件) 本篇内容:ArkTS开发系列之事件(2.8.2手势事件) 一、绑定手势方法 1. 常规手势绑定方法 Text(手势).fontSize(44).gesture(TapGesture().onAct…...

【MATLAB源码-第135期】基于matlab的变色龙群优化算法CSA)机器人栅格路径规划,输出做短路径图和适应度曲线。
操作环境: MATLAB 2022a 1、算法描述 变色龙群优化算法(Chameleon Swarm Algorithm,CSA)是一种新颖的群体智能优化算法,受到自然界中变色龙捕食和社交行为的启发。变色龙以其独特的适应能力而著称,能够根…...
使用Python实现深度学习模型:语言模型与文本生成
语言模型是自然语言处理中的核心任务之一,它们用于预测文本中的下一个单词或生成与输入文本相关的新文本。本文将详细介绍如何使用Python实现一个语言模型,并通过这个模型进行文本生成。 我们将使用TensorFlow和Hugging Face的Transformers库来实现这一任务。 1. 语言模型简…...
大数据面试题之Hive(3)
目录 Hive的函数:UDF、UDAF、UDTF的区别? UDF是怎么在Hive里执行的 row_number,rank,dense_rank的区别 Hive count(distinct)有几个reduce,海量数据会有什么问题 HQL:行转列、列转行 一条HQL从代码到执行的过程 了解Hive S…...
华为OD机考题HJ17 坐标移动
前言 应广大同学要求,开始以OD机考题作为练习题,看看算法和数据结构掌握情况。有需要练习的可以关注下。 描述 开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从&am…...
redis修改密码
在Redis中,修改密码通常涉及编辑Redis配置文件或者在运行时通过Redis命令动态修改。 温馨提示:(运行时直接参考第2条) 1.编辑配置文件: 找到Redis配置文件redis.conf,通常位于/etc/redis/或/usr/local/e…...
《昇思 25 天学习打卡营第 7 天 | 模型训练 》
《昇思 25 天学习打卡营第 7 天 | 模型训练 》 活动地址:https://xihe.mindspore.cn/events/mindspore-training-camp 签名:Sam9029 模型训练 本章节-结合前几张的内容所讲-算是一节综合实践 mindscope 框架使用张量 数据类型数据集下载与加载网络构建函…...
HTML/CSS 基础
1、<input type"checkbox" checked> checked 默认选中为复选框 2、表格中的标题<caption> 3、文字标签直接加 title 4、<dl>为自定义列表的整体,包裹<dt><dd> <dt>自定义列表的主题 <dd>主题的每一项内容 5、…...

Linux系统安装Lua语言及Lua外部库
安装Lua Lua语言是一种轻量级、高效且可扩展的脚本语言,具有简洁易学的语法和占用资源少的特点。它支持动态类型,提供了丰富的表达式和运算符,同时具备自动垃圾回收机制和跨平台性。Lua语言易于嵌入到其他应用程序中,并可与其他语…...

前端技术栈学习:Vue2、Vue cli脚手架、ElementUI组件库、Axios
1 基本介绍 (1)Vue 是一个前端框架, 易于构建用户界面 (2)Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或项目整合 (3)支持和其它类库结合使用 (4&#…...

pycharm中取消Typo:In word ‘xxx‘提示(绿色波浪线提示)的方法
#事故现场 使用pycharm写python代码出现绿色波浪线的提示,并提示Typo:In word ‘xxx’,这是pycharm检测到单词拼写错误、不规范; 那如何取消这种提示呢? #解决方法 方法一:Settings → Editor → Inspections → P…...
js中的浅拷贝和深拷贝
浅拷贝Shallow Copy 浅拷贝只复制对象的顶层属性及其引用,而不复制这些引用所指向的对象。如果原始对象中的某个属性是一个对象或数组,那么浅拷贝后的对象将包含对这个内部对象或数组的引用,而不是这个对象或数组的一个新副本。 let obj1 …...

【Linux】常用基本命令
wget网址用于直接从网上下载某个文件到服务器,当然也可以直接从网上先把东西下到本地然后用filezilla这个软件来传输到服务器上。 当遇到不会的命令时候,可以使用man “不会的命令”来查看这个命令的详细信息。比如我想要看看ls这个命令的详细用法&…...

uniapp——上传图片获取到file对象而非临时地址——基础积累
最近在看uniapp的代码,遇到一个需求,就是要实现上传图片的功能 uniapp 官网地址:https://uniapp.dcloud.net.cn/ 上传图片有对应的API: uni.chooseImage方法:https://uniapp.dcloud.net.cn/api/media/image.html#choo…...

vue3 antdv RadioButton默认值选择问题处理
1、先上官方文档: Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js 官方代码: <template><div><div><a-radio-group v-model:value"value1"><a-radio-button value"a…...

最佳实践,一款基于 Flutter 的桌面应用
前言 这篇文章介绍作为一名后端开发人员,快速的入门前端或者客户端一些相关的技术的心得。先来说说为什么作为一名后端开发人员也需要学习一些前端或者客户端相关的技术。通常来说,深耕一个领域没有错,因为社会常常就是这样分工的࿰…...
python第一个多进程爬虫
使用 multiprocessing 模块实现多进程爬取股票网址买卖数据的基本思路是: 定义爬虫函数,用于从一个或多个股票网址上抓取数据。创建多个进程,每个进程执行爬虫函数,可能针对不同的股票或不同的网页。使用 multiprocessing.Queue …...
在Ubuntu 18.04上安装和配置Ansible的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 配置管理系统旨在简化对大量服务器的控制,适用于管理员和运维团队。它们允许您从一个中央位置以自动化的方式控制许多…...

【详细教程】如何使用YOLOv10进行图片与视频的目标检测
《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...