欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > vue3+antV G6节点与文本框实现

vue3+antV G6节点与文本框实现

2025/3/11 4:26:34 来源:https://blog.csdn.net/Mirs_Zhu/article/details/146068434  浏览:    关键词:vue3+antV G6节点与文本框实现

一、下载第三方包

使用npm下载第三方包:npm install @antv/g6 

二、父组件代码

<template>

  <div id="financialMonitoring" v-loading="loading">

    <retainedProfitsMap

      :securityId="securityId1"

      :symbol="symbol1"

      id="retainedProfitsMap"

      class="mt10"

    />

  </div>

</template>

<script setup lang="ts">

import retainedProfitsMap from './retainedProfitsMap.vue'

const props = defineProps({

  symbol: {

    type: String,

    default: ''

  },

  securityId: {

    type: [String, Number],

    required: true

  }

})

const loading = ref(false) // 加载状态

const securityId1 = ref(props.securityId) // 证券id

const symbol1 = ref(props.symbol) // 证券代码

// 监听参数重新赋值

watch(

  () => [props.securityId, props.symbol],

  (newValue: any, oldValue: any) => {

    if (newValue[0] != oldValue[0]) {

      securityId1.value = newValue[0]

    }

    if (newValue[1] != oldValue[1]) {

      symbol1.value = newValue[1]

    }

    editIndex.value = 1

    dateRange.value = []

    getFinanciaMonitoringData()

  },

  { deep: true }

)

</script>

三、子组件代码

<template>

  <ItemCard title="脑图" v-loading="loading">

    <template #rightPart>

      <el-date-picker

        v-model="dateYear"

        type="year"

        value-format="YYYY"

        placeholder="请选择年份"

        :editable="false"

        :clearable="false"

        :disabled-date="disabledDate"

        @change="changeDate"

        class="year-select"

        ref="datePicker"

      />

    </template>

    <template #otherContent>

      <div id="container"></div>

    </template>

  </ItemCard>

</template>

<script setup lang="ts">

import { ElMessage } from 'element-plus'

import ItemCard from './../RiskWarn/ItemCard.vue'

import G6 from '@antv/g6'

import { queryRetainedProfitsData } from '@/pages/monitor/monitorApi/stockMonitor'

const props = defineProps({

  symbol: {

    // 证券代码

    type: String,

    default: ''

  },

  editIndex: {

    // 变更前后索引

    type: Number,

    default: 1

  }

})

const loading = ref(false) // 加载状态

const dateYear = ref<any>('') // 年份

const symbol1 = ref(props.symbol) // 证券代码

const graphMap = ref() // 脑图dom

const mapData = ref({}) // 脑图数据

const datePicker = ref() // 时间筛选框ref

// 监听参数重新赋值

watch(

  () => [props.symbol],

  (newValue: any, oldValue: any) => {

    if (newValue[0] != oldValue[0]) {

      symbol1.value = newValue[0]

    }

    handleClear()

    getRetainedProfitsData()

  },

  { deep: true }

)

// 获取脑图数据

const getRetainedProfitsData = async () => {

  loading.value = true

  await queryRetainedProfitsData(

    symbol1.value,

    dateYear.value

  ).then((res: any) => {

    if (res.code === 200) {

      dateYear.value = String(res.data.year)

      mapData.value = res.data.mindMap

      initData()

    } else {

      ElMessage({

        type: 'error',

        message: res.message

      })

    }

    loading.value = false

  })

}

// 注册自定义节点

G6.registerNode('custom-node', {

  draw(cfg: any, group: any) {

    const {

      labelCfg = {},

      id,

      num,

      sameRatio,

      numRank,

      sameRatioRank,

      children

    } = cfg

    let keyShape = null

    // 绘制矩形作为节点主体

    const rect = group.addShape('rect', {

      attrs: {

        fill: '#0088FE',

        stroke: '#ffffff',

        radius: 3,

        cursor: children && children.length > 0 ? 'pointer' : '',

        text: id,

        width: Math.max(220, id.length * 4),

        height: 60,

        x: 0,

        y: 0

      }

    })

    group.addShape('text', {

      attrs: {

        ...labelCfg.style,

        cursor: children && children.length > 0 ? 'pointer' : '',

        text: id,

        x: Math.max(220, id.length * 4) / 2,

        y: 60 / 2,

        fontSize: 24,

        fill: '#ffffff'

      }

    })

    group.addShape('rect', {

      attrs: {

        width: 380,

        height: 70,

        x: -90,

        y: 80,

        lineWidth: 1,

        stroke: '#ccc',

        fill: '#ffffff',

        radius: 3,

        fillOpacity: 0

      },

      name: 'num-node'

    })

    group.addShape('text', {

      attrs: {

        text: `数值:${num}`,

        fill: '#333',

        fontSize: 15,

        x: -Math.max(80, id.length * 4) / 4 - 62,

        y: 105

      },

      name: 'num-text'

    })

    group.addShape('text', {

      attrs: {

        text: `行业排名(数值):${numRank}`,

        fill: '#333',

        fontSize: 15,

        x: -Math.max(80, id.length * 4) / 4 + 105,

        y: 105

      },

      name: 'num-text'

    })

    group.addShape('text', {

      attrs: {

        text: `同比:${sameRatio}`,

        fill: '#333',

        fontSize: 15,

        x: -Math.max(80, id.length * 4) / 4 - 62,

        y: 142

      },

      name: 'num-text'

    })

    group.addShape('text', {

      attrs: {

        text: `行业排名(同比):${sameRatioRank}`,

        fill: '#333',

        fontSize: 15,

        x: -Math.max(80, id.length * 4) / 4 + 105,

        y: 142

      },

      name: 'num-text'

    })

    return rect

  }

})

// 控制当前时间之后不能选

const disabledDate = (time: any) => {

  const year = time.getFullYear()

  return year < 2019 || year > new Date().getFullYear()

}

// 改变时间

const changeDate = (value: any) => {

  if (value) {

    dateYear.value = value

    handleClear()

    getRetainedProfitsData()

    datePicker.value.blur()

  }

}

const initData = () => {

  const graph = new G6.TreeGraph({

    container: 'container',

    width: 1410,

    height: 790,

    modes: {

      default: ['drag-canvas', 'zoom-canvas']

    },

    defaultNode: {

      type: 'custom-node',

      anchorPoints: [

        [0, 0.5],

        [1, 0.5]

      ],

      labelCfg: {

        style: {

          fill: '#ffffff',

          fontSize: 20,

          fontWeight: 'normal',

          textAlign: 'center',

          textBaseline: 'middle'

        }

      }

    },

    defaultEdge: {

      type: 'cubic-horizontal',

      style: {

        stroke: '#0088FE',

        lineWidth: 2,

        startArrow: {

          path: 'M 0,0 L 4,3 L 4,-3 Z', // 开始箭头

          fill: '#0088FE'

        }

      }

    },

    layout: {

      type: 'compactBox',

      direction: 'H',

      getVGap: () => {

        return 68

      },

      getHGap: () => {

        return 308

      },

      getSide: () => {

        return 'right'

      }

    }

  })

  graph.data(mapData.value)

  graph.render()

  graph.fitView()

  graphMap.value = graph

  // 脑图点击事件

  graph.on('node:click', (evt: any) => {

    const { item } = evt

    const model = item.getModel()

    haneldCollapse(item, model)

  })

}

// 处理节点展开折叠

const haneldCollapse = (item: any, model: any) => {

  const hasChildren = model.children && model.children.length > 0 ? true : false

  if (!hasChildren) {

    return

  }

  let collapsed = model.collapsed

  collapsed = !collapsed

  model.collapsed = collapsed

  graphMap.value.updateChild(model, model.id)

  const updateParams = {

    collapsed

  }

  graphMap.value.updateItem(item, updateParams)

}

// 清除画布

const handleClear = () => {

  graphMap.value && graphMap.value.destroy()

  graphMap.value = null

}

onMounted(() => {

  getRetainedProfitsData()

})

onBeforeUnmount(() => {

  handleClear()

})

</script>

<style lang="less" scoped>

:deep(.right-part) {

  display: flex;

  align-items: center;

  margin-left: auto;

  .year-select {

    width: 182px;

    height: 28px;

    --el-text-color-regular: #333333;

  }

}

#container {

  width: 1410px;

  height: 790px;

  border: 1px solid #ebeef8;

}

</style>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词