229 lines
6.6 KiB
Vue
229 lines
6.6 KiB
Vue
<template>
|
||
<div class="communityNode-component">
|
||
<div class="graph-container" id="container"></div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { defineProps, onMounted, ref, defineEmits } from "vue"
|
||
import * as echarts from "echarts"
|
||
import nodeHoverImg from "@/assets/images/nodeHover.png"
|
||
import { inject } from "vue"
|
||
let chart = null
|
||
const emit = defineEmits(["click:node"])
|
||
|
||
const initChart = async () => {
|
||
chart = echarts.init(document.getElementById("container"))
|
||
|
||
//处理社团节点
|
||
const nodes = Object.values(inject("communityNodeList") ?? []).map((item) => ({
|
||
id: parseInt(item.id),
|
||
name: parseInt(item.id),
|
||
isIncludePredictNodes: item.isIncludePredictNodes,
|
||
nodesNum: item.nodesNum
|
||
}))
|
||
|
||
const links = [] //待处理
|
||
|
||
const data = { nodes, links }
|
||
|
||
const categories = [
|
||
{ name: "普通社团", category: 0 },
|
||
{ name: "含预测节点社团", category: 1 },
|
||
{ name: "互动隐关系", category: 2 }
|
||
]
|
||
const option = {
|
||
//图例配置
|
||
legend: [
|
||
{
|
||
data: categories.map((c) => ({
|
||
name: c.name,
|
||
itemStyle: {
|
||
color:
|
||
c.category === 0
|
||
? new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 1, color: "#1a3860" }, // 深蓝渐变
|
||
{ offset: 0.5, color: "#38546b" },
|
||
{ offset: 0, color: "#5fb3b3" }
|
||
])
|
||
: c.category === 1
|
||
? new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "#9eec9c" }, // 绿色渐变
|
||
{ offset: 0.37, color: "#aef295" },
|
||
{ offset: 1, color: "#c2f989" }
|
||
])
|
||
: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "#ff9a9e" }, // 红色渐变(用于 category === 2)
|
||
{ offset: 0.5, color: "#fad0c4" },
|
||
{ offset: 1, color: "#fbc2eb" }
|
||
])
|
||
}
|
||
})),
|
||
right: 21,
|
||
bottom: 70,
|
||
icon: "circle",
|
||
orient: "vertical",
|
||
itemWidth: 16,
|
||
itemHeight: 16,
|
||
itemGap: 12,
|
||
backgroundColor: "rgba(0,67,125,0.56)", // 半透明深蓝
|
||
borderRadius: 8, // 圆角
|
||
borderColor: "#c2f2ff", // 淡蓝色边框
|
||
borderWidth: 0.3,
|
||
padding: [12, 20, 12, 20], // 上右下左
|
||
textStyle: {
|
||
color: "#fff",
|
||
fontSize: 16,
|
||
fontWeight: "normal"
|
||
}
|
||
}
|
||
],
|
||
//hover上去的窗口
|
||
tooltip: {
|
||
trigger: "item",
|
||
backgroundColor: "rgba(0,0,0,0)", // 透明背景
|
||
borderColor: "rgba(0,0,0,0)", // 透明边框
|
||
borderWidth: 0,
|
||
|
||
extraCssText: "box-shadow:none;padding:0;",
|
||
formatter: function (params) {
|
||
if (params.dataType === "node") {
|
||
return `<div
|
||
style="
|
||
width: 107px;
|
||
height: 68px;
|
||
border-radius: 4px;
|
||
background: url('${nodeHoverImg}');
|
||
background-size: cover;
|
||
background-position: center;
|
||
background-repeat: no-repeat;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-direction: column;
|
||
">
|
||
<div style="color:#fff;letter-spacing: 0.14px;">
|
||
<div >节点数:${params.data.nodesNum}</div>
|
||
</div>
|
||
</div>`
|
||
}
|
||
return ""
|
||
}
|
||
},
|
||
//权值设置样式
|
||
// edgeLabel: {
|
||
// show: false,
|
||
// position: "middle",
|
||
// formatter: function (params) {
|
||
// return params.data.edge
|
||
// },
|
||
// fontSize: 14
|
||
// },
|
||
emphasis: {
|
||
edgeLabel: {
|
||
show: true,
|
||
color: "#fff",
|
||
fontSize: 18,
|
||
textShadowColor: "#fff",
|
||
textShadowBlur: 0,
|
||
textShadowOffsetX: 0,
|
||
textShadowOffsetY: 0
|
||
}
|
||
},
|
||
series: [
|
||
{
|
||
type: "graph",
|
||
layout: "force",
|
||
animation: false,
|
||
draggable: true,
|
||
roam: true,
|
||
zoom: 0.4,
|
||
categories: categories,
|
||
force: {
|
||
edgeLength: 2000,
|
||
repulsion: 4000,
|
||
gravity: 0.4,
|
||
friction: 0.02,
|
||
coolingFactor: 0.1
|
||
},
|
||
|
||
animationDurationUpdate: 3500, // 节点移动更平滑
|
||
data: data.nodes.map((node) => ({
|
||
...node,
|
||
symbolSize: node.nodesNum / 40 < 30 ? 40 : node.nodesNum / 40,
|
||
itemStyle: {
|
||
color:
|
||
node.isIncludePredictNodes === false
|
||
? new echarts.graphic.RadialGradient(0.98, 0.38, 0.9, [
|
||
{ offset: 1, color: "#1a3860" }, // 最左侧
|
||
{ offset: 0.5, color: "#38546b" }, // 中间
|
||
{ offset: 0, color: "#5fb3b3" } // 最右侧
|
||
])
|
||
: new echarts.graphic.RadialGradient(0.98, 0.38, 0.9, [
|
||
// anchorCount为1的节点渐变(原配色)
|
||
{ offset: 0, color: "#9eec9c" },
|
||
{ offset: 0.37, color: "#aef295" },
|
||
{ offset: 1, color: "#c2f989" }
|
||
]),
|
||
|
||
opacity: 1,
|
||
borderColor: "#46C6AD",
|
||
borderWidth: 1,
|
||
shadowBlur: 4,
|
||
borderType: "dashed",
|
||
shadowColor: "rgba(19, 27, 114, 0.25)"
|
||
},
|
||
emphasis: {
|
||
itemStyle: {
|
||
shadowBlur: 20,
|
||
shadowColor: "#c4a651",
|
||
borderColor: "#fcd267",
|
||
borderWidth: node.isIncludePredictNodes == false ? 1 : 5,
|
||
borderType: "solid"
|
||
}
|
||
}
|
||
})),
|
||
links: data.links,
|
||
lineStyle: {
|
||
color: "#37ACD7",
|
||
width: 1
|
||
},
|
||
emphasis: {
|
||
// 高亮配置
|
||
focus: "adjacency", // 高亮相邻节点
|
||
lineStyle: {
|
||
// 高亮时线条样式
|
||
width: 10 // 线条宽度(10)
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
chart.setOption(option)
|
||
}
|
||
const handleClickNode = () => {
|
||
chart.on("click", function (params) {
|
||
//params.data.name才是社团id
|
||
if (params.dataType === "node") {
|
||
emit("click:node", params.data)
|
||
}
|
||
})
|
||
}
|
||
onMounted(async () => {
|
||
await initChart()
|
||
handleClickNode()
|
||
})
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
.communityNode-component {
|
||
width: 100%;
|
||
height: 100%;
|
||
position: relative;
|
||
.graph-container {
|
||
width: 100%;
|
||
height: 93%;
|
||
}
|
||
}
|
||
</style>
|