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

Vue3 组合式实现 带连接线的Tree型 架构图(一级树形图)

在这里插入图片描述
创建组件名称 TreeNodeView.vue

<template>
  <div class="tree-node">
    <div class="node">{{ rootNodeName }}</div>
    <div class="children" :style="childrenLineStyle">
      <div class="child-node" v-for="node in childNodes" :key="node.id">
        <div class="node">{{ node.name }}</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {computed, ref, onMounted} from 'vue';

const props = defineProps({
  childNodes: {
    type: Array,
    required: true
  },
  rootNodeName: {
    type: String,
    required: true,
  },
});


const childNode = ref(null);
const childrenWidth = ref(null);
const childrenMarginLeft = ref(null);

const childrenLineStyle = computed(() => {
  if (!childNode.value) {
    return {};
  }

  const getWidth = (element) => {
    const style = getComputedStyle(element);
    return parseFloat(style.width) + parseFloat(style.marginLeft) + parseFloat(style.marginRight);
  };

  let allNodeWidth = Array.from(childNode.value).reduce((total, node) => total + getWidth(node), 0);
  const firstNodeWidth = getWidth(childNode.value[0]) / 2;
  let lastNodeWidth = 0;
  if (childNode.value.length > 1) {
    lastNodeWidth = getWidth(childNode.value[childNode.value.length - 1]) / 2;
  }
  childrenWidth.value = `${allNodeWidth - firstNodeWidth - lastNodeWidth}px`;
  childrenMarginLeft.value = `${firstNodeWidth}px`;
  return {};
});

onMounted(() => {
  childNode.value = document.querySelectorAll('.child-node');
});
</script>

<style>
.tree-node {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
}

.node {
  border: 1px solid #000;
  padding: 5px;
  position: relative;
}

.children {
  display: flex;
  justify-content: center;
  position: relative;
  margin-top: 45px;
}

.children::before {
  content: '';
  height: 25px;
  border: 0.00001rem solid #000;
  position: absolute;
  top: -46px;
}

.child-node {
  position: relative;
  margin-left: 10px;
  margin-right: 10px;
}

.child-node::before {
  content: '';
  position: absolute;
  top: -20px;
  left: 50%;
  transform: translateX(-50%);
  height: 20px;
  border-left: 1px solid #000;
}

.children::after {
  content: '';
  position: absolute;
  top: -20px;
  left: 0;
  right: 0;
  border-top: 1px solid #000;
  width: v-bind(childrenWidth);
  margin-left: v-bind(childrenMarginLeft);
}
</style>

<template>
  <div class="tree-node">
    <TreeNodeView v-bind="nodeViewConfig"></TreeNodeView>
  </div>
</template>

<script setup>
import TreeNodeView from "./components/TreeNodeView.vue";

const nodeViewConfig = {
  rootNodeName: '根节点',
  childNodes: [
    {id: 1, name: '节点1-1'},
    {id: 2, name: '节点222222221-2'},
    {id: 3, name: '节点1-3'},
    {id: 4, name: '节点1-4222222'},
    {id: 5, name: '节点1-4'},
    {id: 6, name: '节点1-4'}
  ]
}
</script>

<style scoped>

</style>


http://www.kler.cn/news/157081.html

相关文章:

  • 基于springboot + vue框架的网上商城系统
  • Android多用户初探
  • vscode里面使用vue的一些插件,方便开发
  • Spring Security 6.x 系列(8)—— 源码分析之配置器SecurityConfigurer接口及其分支实现
  • MySQL官网推荐书籍
  • 【接口测试】POST请求提交数据的三种方式及Postman实现
  • 【广州华锐视点】机械零件拆装VR仿真教学系统
  • 【EI会议征稿】第五届人工智能与机电自动化国际学术会议(AIEA 2024)
  • bad_python
  • Vue3实现一个拾色器功能
  • TimeGPT:时间序列预测模型实例
  • TDA4开发环境Docker化
  • 《系统架构设计师教程(第2版)》第2章-计算机系统基础知识-01-计算机硬件
  • Spring中通知是什么
  • Redis7--基础篇4(Redis事务)
  • CocosCreator 面试题(二十) Cocos creator 如何实现一个置灰Shader?
  • [Ubuntu 20.04] 使用Netplan配置网络静态IP
  • RH850P1X芯片学习笔记-Pin Functions
  • 智能优化算法应用:基于松鼠算法无线传感器网络(WSN)覆盖优化 - 附代码
  • 什么是Overlay网络?Overlay网络与Underlay网络有什么区别?
  • 搭建CIG容器重量级监控平台
  • C\C++ 获取最值
  • 无人机覆盖路径规划综述
  • 学习率设置(写给自己看)
  • Redis队列stream,Redis多线程详解
  • Python3+selenium自动化测试框架详解
  • LoadBalancer将服务暴露到外部实现负载均衡Openelb-layer2模式配置介绍
  • 新数字化时代广告的多变式玩法:广告电商
  • 基于Java SSM产品销售管理系统
  • 快速安装Axure RP Extension for Chrome插件