手写顺序流程图组件

效果图

完整代码

<template>
  <div>
    <div class="container" :style="{ width: `${spacingX * (colNum - 1) + itemWidth * colNum}px` }">
      <div
        v-for="(item, i) in recordList"
        :key="i"
        class="list-box"
        :style="{
          marginTop: i < colNum ? '0' : `${spacingY}px`,
          marginRight: i % (2 * colNum) === colNum - 1 || i % (2 * colNum) === colNum ? '0' : `${spacingX}px`,
          order: orderList[i] && orderList[i].order,
          visibility: orderList[i] && orderList[i].itemHide ? 'hidden' : 'visible'
        }"
      >
        <div class="cont-box" :style="{ width: itemWidth + 'px', height: itemHeight + 'px', backgroundColor: '#16a085' }">{{ item }}</div>
        <div v-if="i !== listLen - 1" class="arrow-box" :style="arrowStyle[orderList[i] && orderList[i].arrow]">
          <div class="line-tip" />
          <div class="arrow-tip" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'FlowPath',
  data() {
    return {
      itemWidth: 75, // item宽度
      itemHeight: 75, // item高度
      colNum: 1, // 显示的列数
      spacingX: 40, // 列间距
      spacingY: 40, // 行间距
      rawList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], // 原始数据
      recordList: [], // 列表数据
      arrowStyle: { right: {}, down: {}, left: {}}, // 箭头样式
      orderList: [], // 列表排序序号
      listLen: '' // 列表数据长度
    }
  },
  mounted() {
    this.listLen = this.rawList.length
    this.initFun() // 初始化方法
    window.addEventListener('resize', this.initFun) // 页面宽度变化监听器
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.initFun) // 组件销毁时移除 resize 事件监听器,避免内存泄漏
  },
  methods: {
    /* 初始化方法 */
    initFun() {
      const pageWidth = document.documentElement.clientWidth // 获取页面宽度(可视区域宽度)
      const minTotalWidth = this.itemWidth + this.spacingX // 每个 item(包含间距) 期望的最小总宽度为 minTotalWidth(单位:px)
      const newNum = Math.floor(pageWidth / minTotalWidth) // 计算 colNum,向下取整
      this.colNum = Math.max(newNum, 1) // 限制 colNum 的最小值,比如至少为 1 列
      // 更新箭头样式和列表样式,因为 colNum 变化了,相关布局依赖 colNum 列数
      this.setArrowStyle() // 设置箭头样式
      this.setOrderList() // 设置列表样式
    },
    /* 设置箭头样式 */
    setArrowStyle() {
      const left = {
        width: this.spacingX + 'px',
        top: this.itemHeight / 2 + 'px',
        left: -this.spacingX + 'px'
      }
      const right = {
        width: this.spacingX + 'px',
        top: this.itemHeight / 2 + 'px',
        right: -this.spacingX + 'px',
        transform: 'rotate(180deg)'
      }
      const down = {
        width: this.spacingY + 'px',
        left: this.itemWidth / 2 + 'px',
        bottom: -this.spacingY + 'px',
        transform: 'rotate(-90deg)',
        transformOrigin: 0
      }
      this.arrowStyle = { right, left, down }
    },
    /* 设置列表样式 */
    setOrderList() {
      this.recordList = JSON.parse(JSON.stringify(this.rawList))
      this.orderList = [] // 列表排序序号
      const n = this.colNum // 显示的列数
      const dbn = n * 2 // 列数 * 2
      // 添加占位的 item 项
      const arrLen = this.listLen
      const remainder = (arrLen - 1) % dbn
      if (remainder >= n && remainder < dbn) {
        const diff = dbn - 1 - remainder
        for (let i = 0; i < diff; i++) {
          this.orderList[arrLen + i] = {
            itemHide: true,
            order: arrLen + i
          }
          this.recordList[arrLen + i] = null
        }
      }
      // 设置 item 的箭头方向和顺序
      this.recordList.map((item, index) => {
        const i = index % dbn	// 余数
        if (i >= 0 && i < n) {
          this.orderList[index] = {
            order: index,
            arrow: i !== n - 1 ? 'right' : 'down'
          } // 不用改变顺序
        } else {
          this.orderList[index] = {
            order: index + ((n - 1) - 2 * (i - n)), // i - n 是与最近一侧的距离
            arrow: i !== dbn - 1 ? 'left' : 'down',
            itemHide: this.orderList[index]?.itemHide
          } // 需要改变顺序
        }
      })
    }
  }
}
</script>

<style scoped lang="scss">
.container {
  display: flex;
  flex-wrap: wrap;
  box-sizing: border-box;
  overflow: hidden;
  .list-box {
    position: relative;
    font-size: 20px;
    box-sizing: border-box;
    .cont-box {
    }
  }
}
/* 箭头区域 */
.arrow-box {
  $bgColor: #303133;
  position: absolute;
  // 线条样式
  .line-tip {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    left: 3px;
    width: 90%;
    height: 2px;
    background-color: $bgColor;
  }
  // 箭头样式
  .arrow-tip {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    left: 1px;
    width: 0;
    height: 0;
    border-top: 8px solid transparent;
    border-bottom: 8px solid transparent;
    border-right: 8px solid $bgColor;
  }
}
</style>

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

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

相关文章

html+css+js网页设计 美食 好厨艺西餐美食企业网站模板6个页面

htmlcssjs网页设计 美食 好厨艺西餐美食企业网站模板6个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 …

Vue3中使用 Vue Flow 流程图方法

效果图&#xff1a; 最近项目开发时有一个流程图的功能&#xff0c;需要做流程节点的展示&#xff0c;就搜到了 Vue Flow 这个插件&#xff0c;这个插件总得来说还可以&#xff0c;简单已使用&#xff0c;下边就总结一下使用的方法&#xff1a; Vue Flow官网&#xff1a;https…

37. 数组二叉树

一、题目描述 二叉树只也可以用数组来存储&#xff0c;给定一个数组&#xff0c;树的根节点的值储存在下标1&#xff0c;对于储存在下标n的节点&#xff0c;他的左子节点和右子节点分别储存在下标2n和2n1&#xff0c;并且我们用-1代表一个节点为空&#xff0c;给定一个数组存储…

网关的主要类型和它们的特点

网关&#xff0c;作为网络通信的关键节点&#xff0c;根据其应用场景和功能特点&#xff0c;可以分为多种类型。 1.协议网关 特点&#xff1a; • 协议转换&#xff1a;协议网关的核心功能是转换不同网络之间的通信协议。例如&#xff0c;它可以将IPv4协议的数据包转换为IPv6协…

JAVA学习笔记_JVM

文章目录 初识jvm内存结构程序计数器(寄存器) 栈问题辨析内存溢出 线程诊断本地方法栈Heap堆内存溢出内存诊断 方法区内存溢出常量池 stringTable直接内存垃圾回收 初识jvm JRE JVM 基础类库 JDK JRE 编译工具 JavaSE JDK IDE工具 JavaEE JDK 应用服务器 IDE工具 jvm是…

无线AP安装注意事项

现在的办公楼、酒店等项目中都设计含有网络无线覆盖这一项&#xff0c;在项目实施中&#xff0c;往往采用的是便捷并且后期便于网络无线设备管理的无线ap设备&#xff0c;作为前端无线信号的覆盖。在具体安装无线AP过程中&#xff0c;我们必须要注意以下几点才能保证项目实施完…

PHP框架+gatewayworker实现在线1对1聊天--聊天界面布局+创建websocket连接(5)

文章目录 聊天界面布局html代码 创建websocket连接为什么要绑定&#xff1f; 聊天界面布局 在View/Index目录下创建index.html html代码 <div id"chat"><div id"nbar"><div class"pull-left">与牛德胜正在聊天...</div…

毕设中所学

1、交叉引用 在毕业设计论文Word中交叉引用参考文献_交叉引用如何标注[1~6]-CSDN博客 另&#xff1a;将标号或其他文字改为上标的快捷键是CtrlShift。 图的交叉引用一样&#xff0c;修改引用类型即可。 2、ENVI安装 ENVI5.6 安装教程&#xff0c;新手入门&#xff08;超详细…

xilinx的高速接口构成原理和连接结构及ibert工具的使用-以k7 GTX为例

一、相关简介 Xilinx的高速接口称之为transceivers(高速收发器&#xff09;&#xff0c;这部分的电路是专用电路&#xff0c;供电等都是独立的&#xff0c;根据速率可以分为GTP/GTX/GTH/GTY/GTM等。 Xilinx的高速接口是QUAD为单位的&#xff0c;没一个QUAD由一个时钟COMMON资…

Formality:官方Tutorial(一)

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 本文是对Synopsys Formality User Guide Tutorial中第一个实验的翻译&#xff08;有删改&#xff09;&#xff0c;Lab文件可以从以下链接获取。 Formality官方Tu…

【openwrt】OpenWrt 路由器的 802.1X 动态 VLAN

参考链接 [OpenWrt Wiki] Wi-Fi /etc/config/wirelesshttps://openwrt.org/docs/guide-user/network/wifi/basic#wpa_enterprise_access_point 介绍 基于802.1X 无线网络身份验证࿰

Mac 环境 VVenC 编译与编码命令行工具使用教程

VVenC VVenC 是一个开源的高效视频编码器&#xff0c;专门用于支持 H.266/VVC (Versatile Video Coding) 标准的编码。H.266/VVC 是继 HEVC (H.265) 之后的新一代视频编码标准&#xff0c;主要目的是提供比 HEVC 更高的压缩效率&#xff0c;同时保持或提高视频质量。H.266/VVC…

wx016基于springboot+vue+uniapp的超市购物系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

RTC:实时时钟

RTC&#xff1a;实时时钟 1、实时时钟2、闹钟中断3、秒中断4、输出功能5、BKP的读写6、BKP的侵入事件 1、实时时钟 ①RTC.c #include "RTC.h"/*** brief&#xff1a;RTC初始化函数*/ RCC_PeriphCLKInitTypeDef RTCPeriphClkInit; //RTC时钟配置结构体 RTC_HandleT…

黑马JavaWeb开发跟学(十五).Maven高级

黑马JavaWeb开发跟学.十五.Maven高级 Maven高级1. 分模块设计与开发1.1 介绍1.2 实践1.2.1 分析1.2.2 实现 1.3 总结 2. 继承与聚合2.1 继承2.1.1 继承关系2.1.1.1 思路分析2.1.1.2 实现 2.1.2 版本锁定2.1.2.1 场景2.1.2.2 介绍2.1.2.3 实现2.1.2.4 属性配置 2.2 聚合2.2.1 介…

cka考试-03-k8s版本升级

一、原题 二、解答 [root@master ~]# kubectl get node NAME STATUS ROLES AGE VERSION master Ready control-plane,master 25h v1.22.12 node1 Ready worker 25h v1.22.12 node2 Ready worker …

【Java项目】基于SpringBoot的【垃圾分类系统】

【Java项目】基于SpringBoot的【垃圾分类系统】 技术简介&#xff1a;本系统使用采用B/S架构、Spring Boot框架、MYSQL数据库进行开发设计。 系统简介&#xff1a;使用者分为管理员和用户、垃圾分类管理员&#xff0c;实现功能包括管理员&#xff1a;首页、个人中心、用户管理、…

文本区域提取和分析——Python版本

目录 1. 图像预处理 2. 文本区域提取 3. 文本行分割 4. 文本区域分析 5. 应用举例 总结 文本区域提取和分析是计算机视觉中的重要任务&#xff0c;尤其在光学字符识别&#xff08;OCR&#xff09;系统、文档分析、自动化数据录入等应用中有广泛的应用。其目标是从图像中提…

华为的数字化转型框架和数字化转型成熟度评估方法

2016年&#xff0c;华为公司数字化转型变革规划汇报通过&#xff0c;一系列的变革项目由变革指导委员会(Executive Steering Committee,ESC)完成立项。8年多来&#xff0c;华为数字化转型工作初步取得了一些成果&#xff0c;比如&#xff1a; 实现“销售收入翻番&#xff0c;但…

算法 Class 006(二分搜索)

一、查找一个数 在一个有序数组中查找数字&#xff0c;每次一循环可 砍掉一半的值&#xff0c;只要确定了 arr[mid] 与 num 之间的关系。 大于num 忽略掉 mid及右边的数字 小于 num 忽略掉 mid 及左边的数字 二、 找大于等于 num 的最左位置 意思就是该下标及右边的数都是大于…