Vue-Cropper头像裁剪插件使用

1. 效果预览

在这里插入图片描述

2. 插件介绍

官网地址:[GitHub - xyxiao001/vue-cropper: A simple picture clipping plugin for vue](https://github.com/xyxiao001/vue-cropper?from=thosefree.com)

3 . 插件使用

下载插件

npm install vue-cropper@next

3 . 封装好的代码,拿来用即可

使用注意点

  • 组件内引用-必须

    1.  import 'vue-cropper/dist/index.css'
       import {VueCropper} from 'vue-cropper'
       import {getCurrentInstance, ref, reactive, watch} from 'vue'
      
  • 如下片段可自行更改,

    •   const dp = defineProps({ // 接收父组件参数
            realTime: "", // 实时时间
        })
        
        const de = defineEmits(["popUpClose"])
        
        const avatarUpload = () => { // 图片上传事件
            cropper.value.getCropBlob(data => {
                const formData = new FormData();
                formData.append("id", sessionStorage.getItem("userid"));
                formData.append('mf',data);  // file是你的文件对
                axios.post('/person/uploadAvatar', formData)
                    .then(response => {	// 处理后台返回的结果
                    if(response.code !== 200) return ElMessage.error(response.msg)
                    ElMessage.success(response.msg)
                    de("popUpClose", response.data)
                })
                    .catch(error => { // 处理错误
                    ElMessage.error(error.message)
                    throw error
                });
            })
        }
      

封装组件代码:

<template>

<div class = "avatar-container" @click = "">

    <el-row>
        <el-col :span = "12" style = "width: 600px; height: 300px">
            <vue-cropper
                         ref = "cropper"
                         :img = "options.img"
                         :info = "true"
                         :autoCrop = "options.autoCrop"
                         :autoCropWidth = "options.autoCropWidth"
                         :autoCropHeight = "options.autoCropHeight"
                         :fixedBox = "options.fixedBox"
                         :outputType = "options.outputType"
                         @realTime = "realTime"
                         />
    </el-col>

        <!-- 实时预览部分 -->
        <el-col :span = "12" style = "height: 300px">
            <div class = "preview-box">
                <img v-if = "previews.url" :src = "previews.url" :style="previews.img"/>
                <span v-else></span>
    </div>
    </el-col>

    </el-row>

    <el-row style = "margin-top: 12px">
        <el-col :span = "12">
            <el-row>
                <el-col :span = "8">
                    <el-upload
                               action = "#"
                               :http-request = "() => {}"
                               :before-upload = "beforeUpload"
                               :show-file-list = "false"
                               >
                        <el-button>选择</el-button>
    </el-upload>
    </el-col>
                <el-col :span = "4">
                    <el-button :icon = "Plus" @click = "changeScale(1)"></el-button>
    </el-col>
                <el-col :span = "4">
                    <el-button :icon = "Minus" @click = "changeScale(-1)"></el-button>
    </el-col>
                <el-col :span = "4">
                    <el-button :icon = "RefreshLeft" @click = "rotateLeft()"></el-button>
    </el-col>
                <el-col :span = "4">
                    <el-button :icon = "RefreshRight" @click = "rotateRight()"></el-button>
    </el-col>
    </el-row>
    </el-col>

        <el-col :span = "4" :offset = "8" style = "margin-left: 22.3%">
            <el-button type = "primary" @click = "avatarUpload()">提 交</el-button>
    </el-col>

    </el-row>
    </div>

</template>

<script setup>
    import {Plus, Minus, RefreshLeft, RefreshRight} from '@element-plus/icons-vue'
    import {ElMessage} from 'element-plus'
    import 'vue-cropper/dist/index.css'
    import {VueCropper} from 'vue-cropper'
    import {getCurrentInstance, ref, reactive, watch} from 'vue'
    import axios from "axios";

    const {proxy} = getCurrentInstance()

    const options = reactive({
        img: "https://tse1-mm.cn.bing.net/th/id/OIP-C.rBx_awzG233bGXk-4h3eeAHaFL?w=262&h=184&c=7&r=0&o=5&dpr=1.3&pid=1.7", // 裁剪图片的地址
        autoCropWidth: 200, // 默认生成截图框宽度 默认容器的 80%
        autoCropHeight: 200, // 默认生成截图框高度 默认容器的 80%
        outputType: 'png', // 裁剪生成图片的格式 jpeg, png, webp
        autoCrop: true, // 是否默认生成截图框
        fixedBox: false // 固定截图框大小
    })

    let previews = ref({
        url: '',
        img: '',
    })

    // 修改图片大小 正数为变大 负数变小
    const changeScale = (num) => {
        num = num || 1
        proxy.$refs.cropper.changeScale(num)
    }
    // 向左边旋转90度
    const rotateLeft = () => {
        proxy.$refs.cropper.rotateLeft()
    }
    // 向右边旋转90度
    const rotateRight = () => {
        proxy.$refs.cropper.rotateRight()
    }


    // 上传图片处理
    const beforeUpload = (rawFile) => {
        if (rawFile.type.indexOf('image/') == -1) {
            ElMessage.error('请上传图片类型文件!')
            return false
        }
        if (rawFile.size / 1024 / 1024 > 2) {
            ElMessage.error('文件大小不能超过2MB!')
            return false
        }
        const reader = new FileReader()
        reader.readAsDataURL(rawFile)
        reader.onload = () => {
            // 图片在这里
            if (typeof reader.result === "string") {
                options.img = reader.result
            }
        }
    }
    // 实时预览事件
    const realTime = (data) => {
        previews.value = data
    }

    const cropper = ref(null);

    const getBase64 = () => { // 获取截图的base64编码
        cropper.value.getCropData(data => {
            console.log(data)
        })
    }

    const getBlob = () => { // 获取截图的blob
        cropper.value.getCropBlob(data => {
            console.log(data)
        })
    }

    const dp = defineProps({ // 接收父组件参数
        realTime: "", // 实时时间
    })

    const de = defineEmits(["popUpClose"])

    const avatarUpload = () => { // 图片上传事件
        console.log(sessionStorage.getItem("userid"))
        cropper.value.getCropBlob(data => {
            const formData = new FormData();
            formData.append("id", sessionStorage.getItem("userid"));
            formData.append('mf',data);  // file是你的文件对
            axios.post('/person/uploadAvatar', formData)
                .then(response => {	// 处理后台返回的结果
                if(response.code !== 200) return ElMessage.error(response.msg)
                ElMessage.success(response.msg)
                de("popUpClose", response.data)
            })
                .catch(error => { // 处理错误
                ElMessage.error(error.message)
                throw error
            });
        })
    }


</script>

<style lang = "scss" scoped>
    .avatar-container {
        .img-box {
            border-radius: 50%;
            border: 1px solid #ccc;
            width: 10vw;
            height: 10vw;
        }
    }

    .preview-box {
        position: absolute;
        top: 50%;
        transform: translate(50%, -50%);
        width: 200px;
        height: 200px;
        border-radius: 50%;
        border: 1px solid #ccc;
        overflow: hidden;
    }
</style>

父组件代码 - 【可要可不要】

效果预览

在这里插入图片描述

注意点

  • 根据自己的需求舍 - 留
<script setup>
import {useRoute, useRouter} from 'vue-router';
import {onMounted, reactive, ref} from "vue";
import AvatarUpload from "./avatarUpload.vue";

const router = useRouter()

const rt = reactive({
	personDTO: {}, // 个人信息对象
	show: false,

	realTime: '', // 实时时间
})

const popUpClose = (data) => {
	rt.show = false // 关闭
	rt.personDTO.photo = data // 更新头像
}

let showOverlay = ref(false)

const upload = () => { // 用户头像上传
	if(showOverlay) {
		console.log("uploading avatar")
		rt.show = true
		rt.realTime = new Date().getTime()
	}
}

</script>

<template>
	
	<el-row :gutter = "20">
		<el-col :span = "6"> <!-- 左卡片 -->
			<el-card>
				<div>个人信息</div>
				<el-divider/>
				
				<el-row type = "flex" justify = "center">
					<div
						@mouseover = "showOverlay = true"
						@mouseleave = "showOverlay = false"
						@click = "upload()"
						style = "position: relative; cursor: pointer;">
						<el-avatar :size = "120" :src = "`data:image/png;base64,${rt.personDTO.photo}`"/>
						<div v-if = "showOverlay"
						     style = "position: absolute; border-radius:50%; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center;">
							<span style = "color: white; font-size: 24px;">+</span>
						</div>
					</div>
				</el-row>
				
				<!--弹出编辑-->
				<el-dialog v-model = "rt.show" style = "width:1000px; height: 800px">
					<AvatarUpload @popUpClose = "popUpClose" :realTime = "rt.realTime"/>
				</el-dialog>
				
				<el-divider/>
			
			</el-card>
		</el-col>
		
	</el-row>

</template>


<style scoped>
* {
	font-size: 12px;
}

.el-text-right {
	text-align: right;
}
</style>

EDN ! !!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件实际应用实例,茶楼收银软件管理系统操作流程,茶室计时计费会员管理系统软件试用版教程

软件实际应用实例&#xff0c;茶楼收银软件管理系统操作流程&#xff0c;茶室计时计费会员管理系统软件试用版教程 一、前言 以下软件以 佳易王茶社计时计费管理系统软件V17.9为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、计时计费&…

Nest.js权限管理系统开发(六)新建模块

本文相关文档&#xff1a;NestJS 中文网 创建模块 nest g命令 我们知道一个模块往往包含controller、module、service等文件&#xff0c;为了方便我们创建这些文件&#xff0c;nest cli提供了一些命令&#xff1a; 生成模块 (nest g mo) 以保持代码井井有条并建立清晰的边界…

阿里巴巴Java开发手册解读-黄山版1.7.1

《Java 开发手册》是 Java 社区爱好者的集体智慧结晶和经验总结&#xff0c;经历了多次大规模一线实战的检验及不断完善&#xff0c;整理成册后&#xff0c;众多社区开发者踊跃参与打磨完善&#xff0c;系统化地整理成册&#xff0c;当前的最新版本是黄山版。现代软件行业的高速…

Elasticsearch 创建index库 timeout

问题概述 使用 python 客户端 代码进行创建&#xff0c;【之前成功创建&#xff0c;但是现在出现报错&#xff0c;报错代码es_connection.client.indices.create】 def create_vector_index(dataset_index_name,vector_query_field,query_field):es_connection get_collentio…

【前沿热点视觉算法】-面向显著目标检测的注意区域空间金字塔池网络

计算机视觉算法分享。问题或建议&#xff0c;请文章私信或者文章末尾扫码加微信留言。 1 论文题目 面向显著目标检测的注意区域空间金字塔池网络 2 论文摘要 显著目标检测&#xff08;SOD&#xff09;的最新进展主要依赖于空间空间金字塔池&#xff08;ASPP&#xff09;模块…

java基于微信云开发的智慧校园综合服务(含资讯浏览、场地预约、报修申请、审核管理等功能)微信小程序

java基于微信云开发的智慧校园综合服务&#xff08;含资讯浏览、场地预约、报修申请、审核管理等功能&#xff09;微信小程序 一、演示效果二、流程步骤三、下载链接 一、演示效果 二、流程步骤 1、使用微信小程序官方开发工具导入本项目并开通云开发以及内容管理服务。 2、修…

JANGOW: 1.0.1

kali:192.168.223.128 主机发现 nmap -sP 192.168.223.0/24 端口扫描 nmap -p- 192.168.223.154 开启了21 80端口 web看一下&#xff0c;有个busque.php参数是buscar,但是不知道输入什么&#xff0c;尝试文件包含失败 扫描目录 dirsearch -u http://192.168.223.154 dirse…

Unity中URP下实现水体(水面高光)

文章目录 前言一、实现高光反射原理1、原理&#xff1a;2、公式&#xff1a; 二、实现1、定义 _SpecularColor 作为高光反射的颜色2、定义 _SpecularIntensity 作为反射系数&#xff0c;控制高光反射的强度3、定义 _Smoothness 作为高光指数&#xff0c;用于模型高光范围4、模拟…

python3GUI--酷狗音乐By:PyQt5(附下载地址)

文章目录 一&#xff0e;前言二&#xff0e;展示1.主界面2.乐库3.歌单3.频道4.视频5.我的频道6.视频7.听书8.探索9.其他细节1.搜索中间页2.主菜单3.歌单详情4.托盘菜单 三&#xff0e;心得四&#xff0e;总结 一&#xff0e;前言 之前仿作了几款音乐播放器&#xff0c;有的有功…

使用Scrapy将数据提取到数据库中,进行处理

我们将数据处理的方式&#xff0c;最开始csv文件 再到与数据库建立联系 代码&#xff1a; Spider: import scrapyclass ShuangseqiuSpider(scrapy.Spider):name "shuangseqiu"allowed_domains ["sina.com.cn"]start_urls ["https://view.lottery…

PyTorch深度学习入门与实战

《PyTorch 深度学习入门与实战&#xff08;案例视频精讲&#xff09;》是基于PyTorch 的深度学习入门和实战&#xff0c;结合实际的深度学习案例&#xff0c;由浅入深地介绍PyTorch 在计算机视觉和自然语言处理的相关应用。本书在内容上循序渐进&#xff0c;先介绍了PyTorch 的…

2/26作业

1.link_stack.c #include "link_stack.h" //申请栈顶指针 top_p creat_top() { top_p top (top_p)malloc(sizeof(top_t)); if(topNULL) { printf("空间申请不成功\n"); return NULL; } top->len 0; top->…

Java计划线程池ScheduledThreadPoolExecutor运行流程和源码分析

1. 计划线程池ScheduledThreadPoolExecutor简介 ScheduledThreadPoolExecutor继承自线程池ThreadPoolExecutor&#xff0c;并在其基础上增加了按时间调度执行任务的功能&#xff0c;如果对ThreadPoolExecutor还不是很熟悉&#xff0c;可以阅读一下这篇文章&#xff1a; Java线…

windows安装onlyoffice8.0

安装erlang 安装Erlang25.3 下载地址 设置环境变量 ERLANG_HOME C:\Program Files\Erlang OTP Path下设置%ERLANG_HOME%\bin 打开cmd输入erl不报错即可 安装rabbitmq rabbitmq和erlang对应的关系 下载地址 执行完exe文件后&#xff0c;找到安装目录下的sbin&am…

【JS逆向学习】马蜂窝 cookie 加密(加速乐)

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 本文章未…

四 . 分支和循环——Java基础篇

四 . 分支和循环 1 . switch的基本语法 if 和 swicth 的对比: if既可以用于范围校验, 也可以用于等值校验swicth对于if效率更高,只能用于等值校验 语法格式: switch(表达式){case 常量值1:语句块1;//break;case 常量值2:语句块2;//break; // ...[default:语句块n1;break;] }…

H12-821_77

77.如图所示的交换网络&#xff0c;所有交换机都运行了STP协议&#xff0c;当拓扑稳定后&#xff0c;在以下哪台交换机上修改配置BPDU的发送周期&#xff0c;可以影响STD配置BPDU的发送周期&#xff1f; A.STC B.SWD C.SWA D.SWB 答案&#xff1a;C 注释&#xff1a; 在根桥上…

Mysql 高可用解决方案

1.环境说明 操作系统&#xff1a;centos7.7 主服务器&#xff1a;node2(192.168.1.102) 从服务器&#xff1a;node3(192.168.1.103) keepalived中虚拟ip(VIP):192.168.1.100 2.准备事项 主库和从库数据库的版本一致把主库的数据同步给从库一份 3.主库配置 3.1 编辑MySQL配…

机器学习:朴素贝叶斯算法(Python)

一、朴素贝叶斯算法的实现 naive_bayes_classifier.py import numpy as np import collections as cc # 集合的计数功能 from scipy.stats import norm # 极大似然估计样本的均值和标准方差 from data_bin_wrapper import DataBinsWrapperclass NaiveBayesClassifier:"…

绝对路径拼接漏洞 [NISACTF 2022]babyupload

打开题目 最开始以为是文件上传的漏洞 结果发现无论我们上传什么文件都会显示bad filename 去网上看了大佬的wp知道 我们直接去看源代码得到提示 /source 那我们去访问一下这个路径看看 得到一个下载文件 用记事本打开得到 源代码如下 from flask import Flask, request, r…