vue项目实战 vueCropper 仿微信头像任意区域截取图片,上传到腾讯云保存

在package.json中添加

"vue-cropperjs": "4",

后在控制台执行:npm install

ImageCropper.vue

<template><div v-if="src"><!-- Vue Cropper区域 --><el-row class="cropper-wrapper" v-if="src"><el-col :span="24"><vue-cropper v-if="src":key="cropperKey"ref="cropper" :src="src":style="{ width: width + 'px', height: height + 'px' }"@ready="onReady":dragMode="'move'":viewMode="1":cropBoxResizable="false"/></el-col></el-row><el-row class="button-row" v-if="src"><el-col :span="24"><el-button class="button-soft-orange" @click="cropImage" icon="el-icon-scissors">裁剪图像</el-button><el-button class="button-soft-blue" @click="downloadImage" icon="el-icon-download">下载图像</el-button><el-button class="button-soft-red" @click.prevent="zoom(0.2)" icon="el-icon-zoom-in" /><el-button class="button-soft-red" @click.prevent="zoom(-0.2)" icon="el-icon-zoom-out" /><el-button class="button-soft-yellow" @click.prevent="move(-10, 0)" icon="el-icon-arrow-left" /><el-button class="button-soft-yellow" @click.prevent="move(10, 0)" icon="el-icon-arrow-right" /><el-button class="button-soft-yellow" @click.prevent="move(0, -10)" icon="el-icon-arrow-up" /><el-button class="button-soft-yellow" @click.prevent="move(0, 10)" icon="el-icon-arrow-down" /><el-button class="button-soft-blue" ref="flipX" @click.prevent="flipX" icon="el-icon-sort" /><el-button class="button-soft-blue" ref="flipY" @click.prevent="flipY" icon="el-icon-sort" /><el-button class="button-soft-green" @click.prevent="rotate(90)" icon="el-icon-refresh-right" /><el-button class="button-soft-green" @click.prevent="rotate(-90)" icon="el-icon-refresh-left" /><el-button class="button-soft-gray" @click.prevent="reset" icon="el-icon-refresh" /></el-col></el-row><el-row v-if="croppedImageUrl"><el-col :style="{ width: width + 'px' }" ><el-card><h3>裁剪后预览:</h3><div class="preview-and-buttons"><div class="image-preview-wrapper"><img class="cropped-image-preview" :src="croppedImageUrl" alt="Cropped Image" /></div><div class="upload-button-col"><el-button class="button-soft-green" @click="uploadImageToCos" icon="el-icon-upload">上传到腾讯云</el-button><el-button class="button-soft-gray" @click="resetImage">关闭裁剪区和预览区</el-button></div></div></el-card></el-col></el-row></div></template><script>import VueCropper from "vue-cropperjs"import "cropperjs/dist/cropper.css"import { Button, Row, Col, Card } from "element-ui"import COS from 'cos-js-sdk-v5'export default {components: {VueCropper,'el-button': Button,'el-row': Row,'el-col': Col,'el-card': Card},props: {width: {type: Number,default: 600},height: {type: Number,default: 600},centerWidth: {type: Number}},data() {return {src: '', // 初始 src 为空,等待用户选择本地图片cropperKey: 0, // 用于强制重新渲染 croppercroppedImageUrl: '',uploadedImageUrl: '', // 用于存储上传后返回的 URLflipXValue: 1,flipYValue: 1,cos: null // 用于存储腾讯云COS实例}},mounted() {this.cos = new COS({SecretId: '', // 写自己的腾讯云 SecretIdSecretKey: '' // 写自己的腾讯云 SecretKey});},methods: {onReady() {// 重置画布和裁剪框,确保初始图片位置和大小如重置后的效果this.reset();},onImageChange(event) {const file = event.target.files[0];if (file) {this.src = URL.createObjectURL(file);this.cropperKey++; // 更新 key 强制重新渲染 vue-cropperthis.$emit('imageChanged'); // 通知父组件图片已更换}},cropImage() {this.$refs.cropper.cropper.getCroppedCanvas().toBlob((blob) => {this.croppedImageUrl = URL.createObjectURL(blob);});},downloadImage() {this.$refs.cropper.cropper.getCroppedCanvas().toBlob((blob) => {const link = document.createElement('a');link.href = URL.createObjectURL(blob);link.download = 'cropped_image.png';link.click();});},zoom(scale) {this.$refs.cropper.cropper.zoom(scale);},move(offsetX, offsetY) {this.$refs.cropper.cropper.move(offsetX, offsetY);},flipX() {this.flipXValue = this.flipXValue === 1 ? -1 : 1;this.$refs.cropper.cropper.scaleX(this.flipXValue);},flipY() {this.flipYValue = this.flipYValue === 1 ? -1 : 1;this.$refs.cropper.cropper.scaleY(this.flipYValue);},rotate(degrees) {this.$refs.cropper.cropper.rotate(degrees);},reset() {// 先重置裁剪框和画布确保其他变换恢复到初始状态this.$refs.cropper.cropper.reset();// 获取图片原始尺寸const imageData = this.$refs.cropper.cropper.getImageData();// 计算新的高度const newHeight = (this.centerWidth / imageData.naturalWidth) * imageData.naturalHeight;// 设置画布大小并居中this.$refs.cropper.cropper.setCanvasData({width: this.centerWidth,height: newHeight,left: (this.width - this.centerWidth) / 2,  // 居中画布top: (this.height - newHeight) / 2  // 居中画布});// 设置裁剪框的大小和居中位置this.$refs.cropper.cropper.setCropBoxData({left: (this.width - 300) / 2,  // 居中裁剪框top: (this.height - 200) / 2,   // 居中裁剪框width: 300,height: 200});this.flipXValue = 1;this.flipYValue = 1;},resetImage() {this.src = ''; // 重置 src,使用户可以重新选择图片this.cropperKey++; // 更新 key 强制重新渲染 vue-cropperthis.$emit('imageChanged'); // 通知父组件图片已重置this.croppedImageUrl = ''},uploadImageToCos() {this.uploadedImageUrl = '';this.$emit('uploadStarted'); // 通知父组件上传开始,清空输入框this.$refs.cropper.cropper.getCroppedCanvas().toBlob((blob) => {const timestamp = new Date().getTime(); // 使用时间戳生成唯一文件名const fileName = `cropped_image_${timestamp}.png`; // 生成唯一文件名const file = new File([blob], fileName, { type: "image/png" });this.cos.uploadFile({Bucket: '', // 写自己的腾讯云 BucketRegion: '', // 写自己的腾讯云 Region Key: fileName, // 使用唯一文件名Body: file,SliceSize: 1024 * 1024, // 分块大小,单位为字节,这里设置为1MB}, (err, data) => {if (err) {this.$notify.error({title: '上传失败',message: '图片上传到腾讯云失败,请重试。',duration: 1000});this.$emit('uploadFailed', err); // 通知父组件上传失败} else {this.uploadedImageUrl = data.Location;this.$notify.success({title: '上传成功',message: '图片成功上传到腾讯云。',duration: 1000});this.$emit('uploaded', this.uploadedImageUrl); // 通知父组件上传成功,并发送 URL}});});},openFileInput() {this.$refs.fileInput.click(); // 模拟点击文件输入控件}}}</script><style scoped>.image-select-wrapper {margin-bottom: 20px;}.button-soft-green {background-color: #a5d6a7 !important;border-color: #a5d6a7 !important;color: #fff !important;}.button-soft-orange {background-color: #ffcc80 !important;border-color: #ffcc80 !important;color: #fff !important;}.button-soft-yellow {background-color: #f3c672b4 !important;border-color: #f3c672b4 !important;color: #fff !important;}.button-soft-blue {background-color: #bbd0f8 !important;border-color: #bbd0f8 !important;color: #fff !important;}.button-soft-gray {background-color: #cfd8dc !important;border-color: #cfd8dc !important;color: #fff !important;}.button-soft-red {background-color: #ff8a80 !important;border-color: #ff8a80 !important;color: #fff !important;}.cropper-wrapper {margin-bottom: 20px;}.button-row {margin-bottom: 20px;}.cropped-image-preview {width: 100%;height: 100%;object-fit: cover;}.upload-button-col {display: flex;gap: 10px; /* 水平按钮间距 */align-items: center;}.preview-and-buttons {display: flex;align-items: center;gap: 20px; /* 图片与按钮组之间的间距 */}.image-preview-wrapper {width: 300px!important;/* height: 200px!important; */border: 1px solid #dcdcdc;display: flex;align-items: center;justify-content: center;}.image-preview-wrapper img {max-width: 100%;/* max-height: 100%; */object-fit: cover;}</style>

 TestView.vue 

<template><div :style="{ width: parentWidth + 'px' }"><div class="input-wrapper" :style="{ width: inputWrapperWidth + 'px' }"><el-button @click="openFileInput" style="margin-right: 10px;">选择图片</el-button><el-input :value="uploadedImageUrl" placeholder="上传后的URL" readonly/><input type="file" ref="fileInput" @change="onFileChange" accept="image/*" style="display: none" /></div><ImageCropper ref="imageCropper"@uploaded="handleUploaded" @uploadFailed="handleUploadFailed" @imageChanged="clearUploadedImageUrl"@uploadStarted="clearUploadedImageUrl"@getLocalImageUrl="handleGetLocalImageUrl":width="cropperWidth":height="cropperHeight":center-width="setCenterWidth"style="margin-top: 10px;"/></div>
</template><script>
import ImageCropper from '@/components7/ImageCropper.vue'export default {components: {ImageCropper},data() {return {uploadedImageUrl: '', // 用于存储上传成功后的 URLparentWidth: 1000, // 父组件宽度inputWrapperWidth: 1000, // input-wrapper宽度cropperWidth: 1000, // ImageCropper宽度cropperHeight: 1000, // ImageCropper高度setCenterWidth:900,localImageUrl: '' // 本地图片}},methods: {handleUploaded(url) {this.uploadedImageUrl = url;},handleUploadFailed(err) {console.error('上传失败:', err);},clearUploadedImageUrl() {this.uploadedImageUrl = '';},openFileInput() {this.$refs.fileInput.click();},onFileChange(event) {const file = event.target.files[0];if (file) {this.$refs.imageCropper.onImageChange(event);}},handleGetLocalImageUrl(url) {this.localImageUrl = url;console.log("this.localImageUrl:",this.localImageUrl)}}
}
</script><style scoped>
.input-wrapper {display: flex;align-items: center;
}
.input-wrapper .el-input {flex: 1;
}
</style>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/387798.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue2从基础到实战(指令修饰符)详解

什么是指令修饰符&#xff1f; 指令修饰符就是通过“.”指明一些指令后缀 不同的后缀封装了不同的处理操作 —> 简化代码 按键修饰符 keyup.enter —>当点击enter键的时候才触发 v-model修饰符 v-model.trim —>去除首位空格 v-model.number —>转数字 事件修…

【Vulnhub靶机tomato渗透】

第一步&#xff1a;端口扫描 我使用的是webrobot 访问这个ip&#xff0c;就是它了 第二步&#xff1a;目录扫描 打开kali使用dirb命令扫描http://192.168.189.154下的目录 dirb http://192.168.189.154扫描到目录。 第三步&#xff1a;访问目录地址 看到有几个php的文件 第…

设计模式笔记(一)

目录 设计模式共有23种&#xff0c;也可称为GOF23 单例模式&#xff08;重点&#xff0c;常用&#xff09; 工厂模式 代理模式&#xff1a;&#xff08;SpringAOP的底层原理&#xff09; 静态代理模式&#xff1a;&#xff08;写死一个代理类Proxy&#xff09; 动态代理模…

快速开启react+electron应用,搭建启动问题

注意&#xff1a; React 本地启动在 3000端口Electron 在创建 BrowserWindow 的时候&#xff0c;可以读取本地的文件或者是 url开发环境 读取localhost: 3000生产环境 需要加载本地成型以后的本地文件&#xff0c;打包的时候再考虑 一 react 脚手架 create-react-app 快速搭建…

QT--聊天室

一、设计要求 用QT做一个聊天室&#xff0c; 制作一个服务器和客户端。可以进行注册、登录&#xff0c; 登陆成功后可以使用昵称进行发送、接收消息。 能根据昵称、聊天内容查询历史记录&#xff0c;也可以查询全部聊天记录。 。 二、客户端三级ui界面 三、项目代码 //在…

IDEA管理远程仓库Git

1、模拟项目 新建一个文件夹&#xff0c;用来这次演示 用IDEA来打开文件夹 2、创建仓库 在IDEA中给该文件夹创建本地仓库和远程仓库 在菜单栏找到VCS选择Share project on Gitee 在弹窗中输入描述信息 接下来会出现以下弹窗 点击ADD后&#xff0c;在gitee上会创建远程仓库 …

嵌入式开发服务器与客户端交互 日志2024/7/31

嵌入式开发服务器与客户端交互 客户端 网页 操作 请求相关代码: 这里为了适配 低版本浏览器 用的不是fetch 当然用fetch更好 var curUlr window.location.href; //获取当前网页地址var newURL curUlr.lastIndexOf("/");//截取到最后一个斜杠索引var pathUrl…

mysql 数据库空间统计sql

mysql 数据库空间统计 文章目录 mysql 数据库空间统计说明一、数据库存储代码二、查询某个数据库的所有表的 代码三、列出所有已经产生碎片的表总结 说明 INFORMATION_SCHEMA Table Reference 表参考 information_schema是‌MySQL中的一个特殊数据库&#xff0c;它存储了关于…

MLP多层感知机与Pytorch实现

参考文章&#xff1a; 1.动手学深度学习——多层感知机&#xff08;原理解释代码详解&#xff09;_多层感知机 代码-CSDN博客 2.4.1. 多层感知机 — 动手学深度学习 2.0.0 documentation 3.深度理解多层感知机&#xff08;MLP&#xff09; | 米奇妙妙屋 1. 神经网络由来 神经网…

Scrapy 爬取旅游景点相关数据(七):利用指纹实现“不重复爬取”

本期学习&#xff1a; 利用网页指纹去重 众所周知&#xff0c;代理是要花钱的&#xff0c;那么在爬取&#xff08;测试&#xff09;巨量网页的时候&#xff0c;就不可能对已经爬取过的网站去重复的爬&#xff0c;这样会消耗大量的时间&#xff0c;更重要的是会消耗大量的IP (金…

vite instanceof 失效

背景&#xff1a;给一个巨石单体项目进行标准化模块拆分&#xff0c;封装出来的模块代码用 vite 进行构建&#xff0c;但模块启动后页面上的表现一直和 webpack 那版不一致 一步步 debug 后&#xff0c;发现问题出在下面这个判断条件 const GeneratorFunction function* () …

【Golang 面试 - 基础题】每日 5 题(七)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

Vue 3 中使用 InMap 绘制热力图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 Vue 3 中使用 InMap 绘制热力图 应用场景介绍 InMap 是一款强大的地图组件库&#xff0c;它提供了一系列丰富的可视化功能&#xff0c;包括热力图。热力图可以将数据点在地图上以颜色编码的方式可视化&#x…

微软:警惕利用VMware ESXi进行身份验证绕过攻击

微软于7月29日发布警告&#xff0c;称勒索软件团伙正在积极利用 VMware ESXi 身份验证绕过漏洞进行攻击。 该漏洞被追踪为 CVE-2024-37085&#xff0c;由微软安全研究人员 Edan Zwick、Danielle Kuznets Nohi 和 Meitar Pinto 发现&#xff0c;并在 6 月 25 日发布的 ESXi 8.0 …

如何学习自动化测试工具!

要学习和掌握自动化测试工具的使用方法&#xff0c;可以按照以下步骤进行&#xff1a; 一、明确学习目标 首先&#xff0c;需要明确你想要学习哪种自动化测试工具。自动化测试工具种类繁多&#xff0c;包括但不限于Selenium、Appium、JMeter、Postman、Robot Framework等&…

docker环境安装kafka/Flink/clickhouse镜像

1、安装Kafka服务 1、将一下三个tar文件复制到ubuntu指定目录下 2、进入到/home/cl/app目录&#xff0c;使用docker命令加载tar镜像文件 # cd /home/cl/app # docker load -i kafka.tar # docker load -i kafka-manager.tar # docker load -i kafka-zookeeper.tar3、查看d…

分布式:RocketMQ/Kafka总结(附下载链接)

文章目录 下载链接思维导图 本文总结的是关于消息队列的常见知识总结。消息队列和分布式系统息息相关&#xff0c;因此这里就将消息队列放到分布式中一并进行处理关联 下载链接 链接: https://pan.baidu.com/s/1hRTh7rSesikisgRUO2GBpA?pwdutgp 提取码: utgp 思维导图

web学习笔记(八十三)git

目录 1.Git的基本概念 2.gitee常用的命令 3.解决两个人操作不同文件造成的冲突 4.解决两个人操作同一个文件造成的冲突 1.Git的基本概念 git是一种管理代码的方式&#xff0c;广泛用于软件开发和版本管理。我们通常使用gitee&#xff08;码云&#xff09;来云管理代码。 …

《Linux运维总结:基于x86_64架构CPU使用docker-compose一键离线部署zookeeper 3.8.4容器版分布式集群》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面对不同的客户部署业务系统&#xff0…

前端如何实现更换项目主题色的功能?

1、场景 有一个换主题色的功能&#xff0c;如下图&#xff1a; 切换颜色后&#xff0c;将对页面所有部分的色值进行重新设置&#xff0c;符合最新的主题色。 2、实现思路 因为色值比较灵活&#xff0c;可以任意选取&#xff0c;所以最好的实现方式是&#xff0c;根据设置的…