Vue项目中使用图片裁切器 cropperjs (头像裁切)

cropperjs官方文档

cropperjs结合element-ui 组件后的显示效果:

在这里插入图片描述

1. npm 安装 cropperjs

cmd命令行输入:npm install cropperjs --save

2. 导入相关js和css文件

import 'cropperjs/dist/cropper.css'
import Cropper from 'cropperjs'

在这里插入图片描述

3. 用块元素(容器)包裹图像或画布元素

在这里插入图片描述

4. 设置样式,确保图像的大小完全铺满容器

在这里插入图片描述

5. 初始化裁切器

在这里插入图片描述

<template><div class="settings-container"><!--卡片--><el-card class="box-card"><div slot="header" class="clearfix"><!--面包屑导航--><el-breadcrumb separator-class="el-icon-arrow-right"><el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item><el-breadcrumb-item>个人设置</el-breadcrumb-item></el-breadcrumb></div><!--表单--><el-row><el-col :span="15"><el-form ref="user" :rules="FormRules" :model="user" label-width="100px"><el-form-item label="编号:">{{ user.id }}</el-form-item><el-form-item label="手机:">{{ user.mobile }}</el-form-item><el-form-item label="媒体名称:" prop="name"><el-input v-model="user.name"></el-input></el-form-item><el-form-item label="媒体介绍:" prop="intro"><el-input type="textarea" v-model="user.intro"></el-input></el-form-item><el-form-item label="邮箱:" prop="email"><el-input v-model="user.email"></el-input></el-form-item><el-form-item><el-button type="primary" :loading="updateProfileLoading" @click="onUpdateUser">保存</el-button></el-form-item></el-form></el-col><el-col :span="4" :offset="3">
<!--          <p @click="$refs.file.click()">点击修改头像</p>--><label for="file"><el-avatar shape="square" :size="150" fit="cover" :src="user.photo"></el-avatar><p>点击修改头像</p></label><input @change="onFileChange" id="file" type="file" hidden ref="file"></el-col></el-row></el-card><!--弹出框--><el-dialog@opened="onDialogOpened"@closed="onDialogClosed":append-to-body="true"title="修改头像":visible.sync="dialogVisible"><div class="preview-image-wrap"><img ref="preview-image" class="preview-image" :src="previewImage" alt=""></div><span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="onUpdatePhoto" :loading="updatePhotoLoading">确 定</el-button></span></el-dialog></div>
</template><script>
import { getUserProfile, updateUserPhoto, updateUserProFile } from '../../api/user.js'
import 'cropperjs/dist/cropper.css'
import Cropper from 'cropperjs'
import globalBus from '../../utils/global-bus.js'export default {name: 'SettingsIndex',data () {return {user: {email: '',id: null,intro: '',mobile: '',name: '',photo: ''}, // 用户资料dialogVisible: false, // 上传图片裁切预览的弹出层是否显示previewImage: '', // 预览图片cropper: null, // 裁切器实例updatePhotoLoading: false, // 是否正在更新用户头像 loading显示与否FormRules: {name: [{ required: true, message: '请输入媒体名称', trigger: 'change' },{ min: 3, max: 7, message: '媒体名称长度在 3 到 7 个字符', trigger: 'change' }],intro: [{ required: true, message: '请输入媒体介绍', trigger: 'change' }],email: [{ required: true, message: '请输入邮箱', trigger: 'change' },{validator (rule, value, callback) {if (/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(value)) {callback()} else {callback(new Error('请输入正确的邮箱'))}}}]},updateProfileLoading: false}},methods: {onUpdateUser () {// 表单验证this.$refs.user.validate((valid) => {if (!valid) {this.$message({type: 'warning',message: '表单验证不通过'})return false}this.updateProfileLoading = true// 验证通过,提交表单const { name, intro, email } = this.userupdateUserProFile({name: name,intro: intro,email: email}).then(res => {console.log(res)this.$message({type: 'success',message: '保存成功'})this.updateProfileLoading = false// 发布通知,用户信息已修改globalBus.$emit('update-user', this.user)})})},loadUser () {getUserProfile().then(res => {this.user = res.data.data})},onFileChange () {console.log('file change')// 处理图片预览const file = this.$refs.file// console.log(file.files[0])const blobData = window.URL.createObjectURL(file.files[0])console.log(blobData)this.previewImage = blobData// 展示弹出层,预览用户选择的图片this.dialogVisible = true// 解决选择相同图片不触发change事件的问题this.$refs.file.value = ''},handleClose (done) {this.$confirm('确认关闭?').then(_ => {done()}).catch(_ => {})},// 对话框完全打开后onDialogOpened () {// 图片裁切器必须基于image初始化// 注意:image必须是可见状态才能正常进行初始化// 获取图片DOM节点const image = this.$refs['preview-image']// 第1次初始化好裁切器以后,如果预览裁切的图片发生变化,裁切器默认不会更新图片// 如果需要预览图片发送变化,更新裁切器://    方式一:裁切器.replace()//    方式二:销毁裁切器,重新初始化// 初始化裁切器if (this.cropper) {this.cropper.replace(this.previewImage)}const cropper = new Cropper(image, {aspectRatio: 1 / 1,viewMode: 1,dragMode: 'none',background: true,cropBoxResizable: false// 当你移动裁切器的时候会触发crop方法的调用// crop (event) {//   console.log(event.detail.x)//   console.log(event.detail.y)//   console.log(event.detail.width)//   console.log(event.detail.height)//   console.log(event.detail.rotate)//   console.log(event.detail.scaleX)//   console.log(event.detail.scaleY)// }})this.cropper = cropper},// 对话框完全关闭后onDialogClosed () {// 销毁裁切器// this.cropper.destroy()},onUpdatePhoto () {// 让确定按钮开始显示loadingthis.updatePhotoLoading = true// 获取裁切的图片对象this.cropper.getCroppedCanvas().toBlob(file => {console.log(file)const fd = new FormData()fd.append('photo', file)// 请求提交fd// 请求更新用户头像updateUserPhoto(fd).then(res => {console.log(res)// 关闭对话框this.dialogVisible = false// 更新视图展示// this.user.photo = res.data.data.photo// 直接把裁切结果的文件对象转为blob数据本地预览this.user.photo = window.URL.createObjectURL(file)// 关闭确定按钮的loadingthis.updatePhotoLoading = falsethis.$message({type: 'success',message: '更新头像成功!'})// 发送自定义事件globalBus.$emit('update-user', this.user)})})}},created () {this.loadUser()}
}
</script><style scoped lang="less">
.preview-image-wrap{.preview-image {display: block;max-width: 100%;height: 200px;}
}</style>

6. 图片上传到服务器

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

跳一跳python源码下载_python 微信跳一跳和源码解读

刚好周末&#xff0c;想研究一下前阵子很火的微信跳一跳 下面进入正文。 本文适用对象为WIN10系统&#xff0c;安卓用户。目的在于让丝毫没有接触过Python的小伙伴都能成功运行&#xff0c;如果你恰好是这样的对象&#xff0c;那么跟着我开始操作。我会把我自己的每一步都写下来…

HTML文件上传对象file

window.URL.createObjectURL(fileObj)

Vue项目中使用Echarts(二)

1. 安装&#xff1a; 通过 npm 获取 echarts&#xff0c;npm install echarts --save 2. 最终页面展示效果如下&#xff1a; 三、代码实现 map-demo.vue: <template><!-- 1. 为 ECharts 准备一个具备大小&#xff08;宽高&#xff09;的 DOM --><div ref&quo…

Vue项目中使用百度地图API

百度地图官方文档 1. 申请百度账号和ak 申请 2. 引用百度地图API文件 <script type"text/javascript" src"https://api.map.baidu.com/api?v1.0&&typewebgl&ak您的密钥">3. 设置容器样式 设置容器样式大小 4. 创建地图容器元素 …

8.0/9.0 Email 设置

Email 设置一直都是Odoo的一个坑&#xff0c;巨坑。 先讲结论&#xff0c;发邮件可以用&#xff0c;收还是算了吧 1. 发邮件设置 发的设置相对简单&#xff0c;如果企业邮箱支持catcll all功能&#xff0c;基本不用改动可以直接用&#xff0c;否则需要安装第三方模块&#xff0…

Vue v-model 指令详解以及sync修饰符的使用场景(结合父子组件通信案例)

参考Vue官方文档 一、需求如下&#xff1a; 二、代码如下 三、分步解析&#xff1a; 父组件给子组件传值&#xff1a; 子组件给父组件传值&#xff1a; 四、sync修饰符的使用 vue.js官方文档 如果已经使用了v-model双向绑定了一个数据&#xff0c;但是还想要实现另一个数…

stm32F1使用SD卡实现IAP

最近在做一个项目&#xff0c;想使用uSD卡来实现在应用编程&#xff0c;首先需要一些知识 我所使用的单片机是STM32F103ZE&#xff0c;内部flash&#xff0c;超始地址为0x8000000&#xff0c;大小为0x80000&#xff08;0x80000/1024也就是512kByte&#xff09;要实现IAP&#x…

父组件访问子组件中的数据(父子组件通信案例:父组件访问子组件$refs[‘子组件‘],子组件传递数据给父组件(父组件中使用v-model))

一、需求 二、在父组件upload-cover中&#xff1a; 通过$refs[子组件的ref属性值]就能拿到子组件对象 三、在子组件imgae-list&#xff08;相对于父组件upload-cover来说&#xff0c;image-list组件是子组件&#xff09;中 通过在data中定义一个selected&#xff0c;来保存…

[设计模式]6. C++与职责链模式(chain of rsponsibility pattern)

默默地EEer&#xff0c;原文地址&#xff1a; http://www.cnblogs.com/hebaichuanyeah/p/5625233.html 职责链模式指使多个对象多有机会处理请求&#xff0c;避免请求发送者和接受者的耦合关系。 将这些接受处理的对象连成一条链&#xff0c;并沿着该链处理请求。 一个传说中的…

python删除为空值的列_python如何删除列为空的行

1.摘要 dropna()方法&#xff0c;能够找到DataFrame类型数据的空值&#xff08;缺失值&#xff09;&#xff0c;将空值所在的行/列删除后&#xff0c;将新的DataFrame作为返回值返回。 2.函数详解 函数形式&#xff1a;dropna(axis0, howany, threshNone, subsetNone, inplaceF…

axios请求拦截器、响应拦截器、vue-router路由导航守卫的使用(案例)

axios官方文档 一、请求拦截器 设置headers,给所有请求加上Authorization&#xff1a;token值 二、响应拦截器 直接去访问/article,发现可以进入到article内容管理页面 原因是在vue路由拦截器中&#xff0c;我们是这样来判断用户是否有权限访问除了登录页面之外的其他页面&a…

Vue项目部署,打包发布上线

参考vuecli官方文档 一、构建打包 在发布上线之前&#xff0c;我们需要执行构建打包&#xff0c;将 .less、.vue、.js 等相关资源进行编译打包&#xff0c;转换成浏览器可以直接识别运行的普通 css、js、html。 # yarn run build 或者 yarn build npm run buildVueCLI 会把打…

spring源码编译和导入eclipse

1、下载源码并解压 https://github.com/spring-projects/spring-framework/tree/v3.2.5.RELEASE 2、源码编译 cmd进入spring源码根目录&#xff0c;执行编译源码&#xff1a;gradlew build可能出现问题&#xff1a;&#xff08;1&#xff09;如果出现某些方法找不到&#xff0…

大学python教材思维导图_Python核心知识体系的14张思维导图

本文主要涵盖了 Python 编程的核心知识&#xff08;暂不包括标准库及第三方库&#xff09;。 按顺序依次展示了以下内容的一系列思维导图&#xff1a;基础知识&#xff0c;数据类型&#xff08;数字&#xff0c;字符串&#xff0c;列表&#xff0c;元组&#xff0c;字典&#x…

华为OJ平台——整形数组合并

题目描述&#xff1a; 将两个整型数组按照升序合并&#xff0c;并且过滤掉重复数组元素 输入&#xff1a; 输入说明&#xff0c;按下列顺序输入&#xff1a;    1 输入第一个数组的个数    2 输入第一个数组的数值    3 输入第二个数组的个数    4 输入第二个数…

python 函数式编程包_python 函数支持函数式编程的包operator partial

itemgetter和attrgetter能替代从序列中取出元素或读取对象属性的lambda表达式&#xff0c;会自动构建函数 itemgetter 1&#xff0c;根据元组某个字段给元组列表排序&#xff0c;下例中 itemgetter(1) lambda field : field[1] 2,如果把多个参数传给itemgetter ,它构建的函数会…

Node中使用token(基于第三方包jsonwebtoken)

一、jsonwebtoken 用于生成token&#xff08;加密&#xff09; > jsonwebtoken 1. 安装 npm i jsonwebtoken --save 2. 使用 2.1 引入 2.2 加密 用户登录成功后&#xff0c;后端生成token&#xff0c;返回给前端 二、passport、passport-jwt 用于验证token&#xff0…

concurrently同时开启多个监听服务

当我们使用nodejs和vue混合开发的时候。当要同时启动后台服务&#xff0c;和前端服务的时候&#xff0c;我们可以使用concurrently 一、安装concurrently包 npm install concurrently --save-dev 二、配置 配置vuecli创建的项目中的packag.json文件&#xff1a; 2. 配置node…

vue-cli4.x 中 配置允许跨域请求

在项目根目录下创建vue.config.js文件&#xff1a; vue.config.js: module.exports {devServer: {host: localhost,port: 8080,https: false,open: false, // 配置自动启动浏览器hotOnly: true, // 是否热更新proxy: {/api: { // 路径中有 /api 的请求都会走这个代理target: …

怎样不停请求接口实现实时刷新_快狗打车实时数仓和基于Hologres的数据服务建设...

前言 数据的实时化是最近几年数据行业很重要的趋势&#xff0c;我们在去年底也建立起新一代的实时数仓&#xff0c;但是在数据应用上一直没有取得很大的突破&#xff0c;我们希望实时数仓不仅仅是支撑大屏、核心实时报表、个别实时应用等简单的场景&#xff0c;希望更大…