当前位置: 首页 > backend >正文

vue使用vue-cropper实现图片裁剪之单图裁剪

vue制作的pc系统中(如若依系统),需要实现按照固定尺寸进行裁剪后再进行图片上传,以下代码讲述的是实现单张图片裁剪上传。

1.第一步需要安装vue-cropper
npm install vue-cropper
2.第二步在需要的页面进入代码引入

import {VueCropper} from "vue-cropper"
3.第三步封装子组件
<template><div><div class="user-info-head" @click="editCropper()"><img v-bind:src="options.img" title="点击上传头像" class="img-lg" /></div><el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened"  @close="closeDialog"><el-row><el-col :xs="24" :md="12" :style="{height: '350px'}"><vue-cropperref="cropper":img="options.img":info="true":autoCrop="options.autoCrop":autoCropWidth="options.autoCropWidth":autoCropHeight="options.autoCropHeight":fixedBox="options.fixedBox":outputType="options.outputType"@realTime="realTime"v-if="visible"/></el-col><el-col :xs="24" :md="12" :style="{height: '350px'}"><div class="avatar-upload-preview-update"><img :src="previews.url" :style="previews.img" /></div></el-col></el-row><br /><el-row><el-col :lg="2" :sm="3" :xs="3"><el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload"><el-button size="small">选择<i class="el-icon-upload el-icon--right"></i></el-button></el-upload></el-col><el-col :lg="{span: 1, offset: 2}" :sm="2" :xs="2"><el-button icon="el-icon-plus" size="small" @click="changeScale(1)"></el-button></el-col><el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2"><el-button icon="el-icon-minus" size="small" @click="changeScale(-1)"></el-button></el-col><el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2"><el-button icon="el-icon-refresh-left" size="small" @click="rotateLeft()"></el-button></el-col><el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2"><el-button icon="el-icon-refresh-right" size="small" @click="rotateRight()"></el-button></el-col><el-col :lg="{span: 2, offset: 6}" :sm="2" :xs="2"><el-button type="primary" size="small" @click="uploadImg()">提 交</el-button></el-col></el-row></el-dialog></div>
</template><script>
import store from "@/store"
import { VueCropper } from "vue-cropper"
import { uploadCommonImg } from "@/api/system/user"
import { debounce } from '@/utils'export default {components: { VueCropper },props: {url: {type: String,default: ""},},data() {return {// 是否显示弹出层open: false,// 是否显示croppervisible: false,// 弹出层标题title: "修改头像",options: {img: '',  //裁剪图片的地址autoCrop: true,             // 是否默认生成截图框autoCropWidth: 162,         // 默认生成截图框宽度autoCropHeight: 200,        // 默认生成截图框高度fixedBox: true,             // 固定截图框大小 不允许改变outputType:"png",           // 默认生成截图为PNG格式filename: 'avatar'          // 文件名称},previews: {},resizeHandler: null}},mounted() {this.options.img= this.url?(process.env.VUE_APP_BASE_API +this.url):''},methods: {// 编辑头像editCropper() {this.open = true},// 打开弹出层结束时的回调modalOpened() {this.visible = trueif (!this.resizeHandler) {this.resizeHandler = debounce(() => {this.refresh()}, 100)}window.addEventListener("resize", this.resizeHandler)},// 刷新组件refresh() {this.$refs.cropper.refresh()},// 覆盖默认的上传行为requestUpload() {},// 向左旋转rotateLeft() {this.$refs.cropper.rotateLeft()},// 向右旋转rotateRight() {this.$refs.cropper.rotateRight()},// 图片缩放changeScale(num) {num = num || 1this.$refs.cropper.changeScale(num)},// 上传预处理beforeUpload(file) {if (file.type.indexOf("image/") == -1) {this.$modal.msgError("文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。")} else {const reader = new FileReader()reader.readAsDataURL(file)reader.onload = () => {this.options.img = reader.resultthis.options.filename = file.name}}},// 上传图片uploadImg() {this.$refs.cropper.getCropBlob(data => {let formData = new FormData()formData.append("file", data, this.options.filename)uploadCommonImg(formData).then(response => {this.open = falsethis.options.img = process.env.VUE_APP_BASE_API + response.fileNameconsole.log('this.options.img',this.options.img)this.$emit('outUrl', response.fileName)this.visible = false})})},// 实时预览realTime(data) {this.previews = data},// 关闭窗口closeDialog() {// this.options.img =''this.visible = falsewindow.removeEventListener("resize", this.resizeHandler)}}
}
</script>
<style scoped lang="scss">
.user-info-head {position: relative;display: inline-block;height: 120px;
}.user-info-head:hover:after {content: '+';position: absolute;left: 0;right: 0;top: 0;bottom: 0;color: #eee;background: rgba(0, 0, 0, 0.5);font-size: 24px;font-style: normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;cursor: pointer;line-height: 110px;//border-radius: 50%;text-align: center;
}
</style>
4.第四步,父级页面引入该子组件
 //其中url是父组件进行子组件的初始化传值  outUrl是接收子组件传递过来的参数 <imgCrop @outUrl="getUrl" :url="form.peoImage"/>
5.第五步 接收子组件传递过来的参数
 getUrl(url) {this.form.peoImage = url},

因为我用的若依系统,ruoyi.css中集成了上述组件中的样式 ,粘贴如下:

/**
* 通用css样式布局处理
* Copyright (c) 2019 ruoyi
*//** 基础通用 **/
.pt5 {padding-top: 5px;
}.pr5 {padding-right: 5px;
}.pb5 {padding-bottom: 5px;
}.mt5 {margin-top: 5px;
}.mr5 {margin-right: 5px;
}.mb5 {margin-bottom: 5px;
}.mb8 {margin-bottom: 8px;
}.ml5 {margin-left: 5px;
}.mt10 {margin-top: 10px;
}.mr10 {margin-right: 10px;
}.mb10 {margin-bottom: 10px;
}
.ml10 {margin-left: 10px;
}.mt20 {margin-top: 20px;
}.mr20 {margin-right: 20px;
}.mb20 {margin-bottom: 20px;
}
.ml20 {margin-left: 20px;
}.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {font-family: inherit;font-weight: 500;line-height: 1.1;color: inherit;
}.el-message-box__status + .el-message-box__message{word-break: break-word;
}.el-dialog:not(.is-fullscreen) {margin-top: 6vh !important;
}.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body {overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;
}.el-table {.el-table__header-wrapper, .el-table__fixed-header-wrapper {th {word-break: break-word;background-color: #f8f8f9;color: #515a6e;height: 40px;font-size: 13px;}}.el-table__body-wrapper {.el-button [class*="el-icon-"] + span {margin-left: 1px;}}
}/** 表单布局 **/
.form-header {font-size: 15px;color: #6379bb;border-bottom: 1px solid #ddd;margin: 8px 10px 25px 10px;padding-bottom: 5px
}/** 表格布局 **/
.pagination-container {display: flex;justify-content: flex-end;margin-top: 20px;
}/* tree border */
.tree-border {margin-top: 5px;border: 1px solid #e5e6e7;background: #FFFFFF none;border-radius: 4px;
}@media (max-width: 768px) {.pagination-container .el-pagination > .el-pagination__jump {display: none !important;}.pagination-container .el-pagination > .el-pagination__sizes {display: none !important;}
}.el-table .fixed-width .el-button--mini {padding-left: 0;padding-right: 0;width: inherit;
}/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine {cursor: pointer;margin-left: 5px;
}.el-table .el-dropdown, .el-icon-arrow-down {font-size: 12px;
}.el-tree-node__content > .el-checkbox {margin-right: 8px;
}.list-group-striped > .list-group-item {border-left: 0;border-right: 0;border-radius: 0;padding-left: 0;padding-right: 0;
}.list-group {padding-left: 0px;list-style: none;
}.list-group-item {border-bottom: 1px solid #e7eaec;border-top: 1px solid #e7eaec;margin-bottom: -1px;padding: 11px 0px;font-size: 13px;
}.pull-right {float: right !important;
}.el-card__header {padding: 14px 15px 7px;min-height: 40px;
}.el-card__body {padding: 15px 20px 20px 20px;
}.card-box {margin-bottom: 10px;
}/* button color */
.el-button--cyan.is-active,
.el-button--cyan:active {background: #20B2AA;border-color: #20B2AA;color: #FFFFFF;
}.el-button--cyan:focus,
.el-button--cyan:hover {background: #48D1CC;border-color: #48D1CC;color: #FFFFFF;
}.el-button--cyan {background-color: #20B2AA;border-color: #20B2AA;color: #FFFFFF;
}/* text color */
.text-navy {color: #1ab394;
}.text-primary {color: inherit;
}.text-success {color: #1c84c6;
}.text-info {color: #23c6c8;
}.text-warning {color: #f8ac59;
}.text-danger {color: #ed5565;
}.text-muted {color: #888888;
}/* image */
.img-circle {border-radius: 50%;
}.img-lg {width: 120px;height: 120px;
}.avatar-upload-preview {position: relative;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 200px;height: 200px;border-radius: 50%;box-shadow: 0 0 4px #ccc;overflow: hidden;
}
.avatar-upload-preview-update {position: relative;top: 50%;left: 50%;transform: translate(-50%, -50%);width:162px;height: 200px;//border-radius: 50%;box-shadow: 0 0 4px #ccc;overflow: hidden;
}
.swiper-upload-preview-update {position: relative;top: 50%;left: 50%;transform: translate(-50%, -50%);width:352px;height: 150px;//border-radius: 50%;box-shadow: 0 0 4px #ccc;overflow: hidden;
}
/* 拖拽列样式 */
.sortable-ghost {opacity: .8;color: #fff !important;background: #42b983 !important;
}.top-right-btn {position: relative;float: right;
}/* 分割面板样式 */
.splitpanes.default-theme .splitpanes__pane {background-color: #fff!important;
}

6.至此完结。

http://www.xdnf.cn/news/18171.html

相关文章:

  • 关于mybatis表关联查询和mybatis-Plus单表查询传入时间查询数据(走索引)
  • Linux Namespace 隔离的“暗面”——故障排查、认知误区与演进蓝图
  • CVPR 2025 | 具身智能 | HOLODECK:一句话召唤3D世界,智能体的“元宇宙练功房”来了
  • 【HTML】3D动态凯旋门
  • 通过C#上位机串口写入和读取浮点数到stm32的片内flash实战4(通过串口下发AD9833设置值并在上位机显示波形曲线)
  • “你不干有的是AI干”,提示词中的“情感化提示”
  • 如何在 Ubuntu Linux 上安装 RPM 软件包
  • 【SQL优化案例】统计信息缺失
  • Vercel v0 iOS版重磅发布:AI驱动的移动开发新篇章
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘paramiko’问题
  • C++入门自学Day14-- Stack和Queue的自实现(适配器)
  • Java高级面试实战:Spring Boot微服务与Redis缓存整合案例解析
  • “R语言+遥感”的水环境综合评价方法实践技术应用
  • Centos7物理安装 Redis8.2.0
  • 【GNSS定位原理及算法杂记6】​​​​​​PPP(精密单点定位)原理,RTK/PPK/PPP区别讨论
  • 【部署相关】DockerKuberbetes常用命令大全(速查+解释)
  • 孩子王披露半年报:多数据持续增长,全年预期增强
  • git仓库和分支的关系
  • Linux GPIO子系统中开漏模式软件仿真机制的深度分析
  • 【深度学习计算性能】06:多GPU的简洁实现
  • 树状数组/差分数组/线段树/莫队算法介绍
  • 政务窗口服务满意度调查:服务型政府建设赋能方案(北京市场调研)
  • 2025年12大AI测试自动化工具
  • 电子电气架构 --- 软件项目风险管理
  • 「内力探查术」:用 Instruments 勘破 SwiftUI 卡顿迷局
  • Android Coil 3拦截器Interceptor计算单次请求耗时,Kotlin
  • 软件测试-Selenium学习笔记
  • Node.js 在 Windows Server 上的离线部署方案
  • Linux系统安全补丁管理与自动化部署研究与实现(LW+源码+讲解+部署)
  • 2.Kotlin 集合 List 所有方法