relation-chart.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <template>
  2. <div class="relation-chart" ref="ref_main">
  3. <div class="chart" id="container"/>
  4. </div>
  5. </template>
  6. <script setup lang="ts">
  7. import {getCurrentInstance, onMounted, reactive, ref, watch} from "vue";
  8. import {Graph} from "@antv/g6";
  9. const emit = defineEmits(['chartPage'])
  10. const {proxy} = getCurrentInstance()
  11. const props = defineProps({
  12. data: {}
  13. })
  14. const state: any = reactive({
  15. resizeObserver: <any>null,
  16. })
  17. const ref_main = ref()
  18. const setNodes = (data) => {
  19. data.nodes.forEach(v => {
  20. v.style = {
  21. badge: true,
  22. badges:[{text: String(v.num), placement: 'top-right', offsetX: -10, offsetY: 10}],
  23. // icon: false,
  24. iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',
  25. }
  26. })
  27. }
  28. const setEdges = (data) => {
  29. data.edges.forEach(v => {
  30. v.style = {
  31. labelText: '关系描述'
  32. }
  33. })
  34. }
  35. const initChart = () => {
  36. if (props.data?.nodes?.length > 0) {
  37. const data = JSON.parse(JSON.stringify(props.data))
  38. setNodes(data)
  39. setEdges(data)
  40. const mainColor = getComputedStyle(document.documentElement).getPropertyValue('--cus-main-color')
  41. const mainColorHex2 = getComputedStyle(document.documentElement).getPropertyValue('--cus-main-color-hex-2')
  42. const graph = new Graph({
  43. container: 'container',
  44. data,
  45. // autoResize: true,
  46. autoFit: 'view',
  47. behaviors: ['drag-canvas', 'drag-element', 'zoom-canvas', {
  48. type: 'click-select',
  49. degree: 1,
  50. enable: (event) => event.targetType === "node",
  51. }],
  52. layout: {
  53. type: 'radial',
  54. focusNode: '3',
  55. linkDistance: 200,
  56. preventOverlap: true,
  57. unitRadius: 200,
  58. maxPreventOverlapIteration: 100,
  59. strictRadial: false
  60. },
  61. node: {
  62. style: {
  63. // circle
  64. size: (v) => v.weight,
  65. fill: 'transparent',
  66. lineWidth: 2,
  67. stroke: mainColor,
  68. // label
  69. label: true,
  70. labelPlacement: 'bottom',
  71. labelText: (v) => v.name,
  72. labelFill: '#ffffff',
  73. labelPadding: [4, 10],
  74. labelBackground: true,
  75. labelBackgroundFill: mainColor,
  76. labelBackgroundRadius: 2,
  77. labelFontSize: 14,
  78. labelOffsetY: 6,
  79. // badge
  80. badgeFontSize: 12,
  81. badgePadding: [2, 4, 0, 4],
  82. badgeBackgroundFill: mainColor,
  83. halo: false,
  84. haloLineDash: 0,
  85. haloLineWidth: 12,
  86. haloStrokeOpacity: 0.25,
  87. },
  88. state: {
  89. selected: {
  90. lineWidth: 4,
  91. stroke: mainColor,
  92. labelFontSize: 14,
  93. labelFontWeight: 'normal',
  94. }
  95. }
  96. },
  97. edge: {
  98. style: {
  99. endArrow: true,
  100. endArrowType: 'triangle',
  101. endArrowSize: 8,
  102. stroke: mainColor,
  103. labelAutoRotate: false,
  104. labelFill: '#ffffff',
  105. labelPadding: [2, 4, 0, 4],
  106. labelBackground: true,
  107. labelBackgroundFill: mainColor,
  108. labelBackgroundRadius: 20,
  109. labelFontSize: 12,
  110. halo: true,
  111. haloLineDash: 4,
  112. haloLineWidth: 2,
  113. },
  114. state: {
  115. selected: {
  116. labelFontSize: 12,
  117. labelFontWeight: 'normal'
  118. }
  119. }
  120. },
  121. } as any);
  122. graph.render();
  123. graph.on('node:click', (e) => {
  124. emit('chartPage', e.target.id)
  125. })
  126. state.resizeObserver = new ResizeObserver((entries) => {
  127. for (const entry of entries) {
  128. graph && graph?.resize()
  129. }
  130. })
  131. state.resizeObserver.observe(ref_main.value);
  132. }
  133. }
  134. watch(() => props.data, () => {
  135. initChart()
  136. })
  137. onMounted(() => {
  138. return () => {
  139. state.resizeObserver?.unobserve(ref_main?.value)
  140. state.resizeObserver?.disconnect()
  141. }
  142. })
  143. </script>
  144. <style lang="scss" scoped>
  145. .relation-chart {
  146. width: 100%;
  147. height: 100%;
  148. background-color: rgba(var(--cus-main-color-rgb), 0.1);
  149. .chart {
  150. width: 100%;
  151. height: 100%;
  152. }
  153. }
  154. </style>