diff --git a/object/dataset_graph.go b/object/dataset_graph.go index 13c9075..9f3c2a4 100644 --- a/object/dataset_graph.go +++ b/object/dataset_graph.go @@ -100,13 +100,14 @@ func generateGraph(vectors []*Vector) *Graph { for _, vector := range vectors { //value := 5 value := int(math.Sqrt(float64(nodeWeightMap[vector.Name]))) + 3 + weight := nodeWeightMap[vector.Name] //nodeColor := "rgb(232,67,62)" //nodeColor := getNodeColor(value) nodeColor := vector.Color fmt.Printf("Node [%s]: weight = %d, nodeValue = %d\n", vector.Name, nodeWeightMap[vector.Name], value) - g.addNode(vector.Name, vector.Name, value, nodeColor, "") + g.addNode(vector.Name, vector.Name, value, nodeColor, vector.Category, weight) } return g diff --git a/object/graph.go b/object/graph.go index 2c89166..c4f68a9 100644 --- a/object/graph.go +++ b/object/graph.go @@ -1,20 +1,22 @@ package object type Node struct { - Id string `json:"id"` - Name string `json:"name"` - Value int `json:"val"` - Color string `json:"color"` - Tag string `json:"tag"` + Id string `json:"id"` + Name string `json:"name"` + Value int `json:"val"` + Color string `json:"color"` + Tag string `json:"tag"` + Weight int `json:"weight"` } -func newNode(id string, name string, value int, color string, tag string) *Node { +func newNode(id string, name string, value int, color string, tag string, weight int) *Node { n := Node{} n.Id = id n.Name = name n.Value = value n.Color = color n.Tag = tag + n.Weight = weight return &n } @@ -48,8 +50,8 @@ func newGraph() *Graph { return &g } -func (g *Graph) addNode(id string, name string, value int, color string, tag string) { - n := newNode(id, name, value, color, tag) +func (g *Graph) addNode(id string, name string, value int, color string, tag string, weight int) { + n := newNode(id, name, value, color, tag, weight) g.Nodes = append(g.Nodes, n) } diff --git a/web/src/Dataset.js b/web/src/Dataset.js index 5fc7feb..e0cbb10 100644 --- a/web/src/Dataset.js +++ b/web/src/Dataset.js @@ -1,5 +1,5 @@ import React from "react"; -import {Card, Col, Empty, Row, Slider, Spin, Switch} from "antd"; +import {Card, Col, Empty, List, Row, Slider, Spin, Switch} from "antd"; import ForceGraph2D from 'react-force-graph-2d'; import ForceGraph3D from 'react-force-graph-3d'; import * as d3 from "d3-force"; @@ -45,6 +45,7 @@ class Dataset extends React.Component { distanceMax: 100, selectedType: null, selectedId: null, + selectedIds: [], } } @@ -65,8 +66,58 @@ class Dataset extends React.Component { }); } + renderNodeMenu(selectedIds) { + return ( + + 节点个数:{selectedIds.length} + + } + dataSource={selectedIds} + renderItem={item => { + return ( + + {`${item.id} | ${item.weight}`} + + ) + }} + pagination={{pageSize: 20, size: "small", showLessItems: true, simple: true}} + /> + ) + } + renderLeftToolbar() { - return null; + if (this.state.graph === null) { + return; + } + + let selectedIds = this.state.graph.nodes; + let categoryName = "全部"; + if (this.state.selectedIds.length !== 0) { + selectedIds = this.state.selectedIds; + categoryName = this.state.selectedIds[0].tag; + } + + selectedIds = selectedIds.sort((a, b) => {return b.weight - a.weight;}); + + return ( +
+
+ + 分类:{categoryName} +
+ } type="inner"> + { + this.renderNodeMenu(selectedIds) + } + +
+ + ) } renderRightToolbar() { @@ -174,6 +225,10 @@ class Dataset extends React.Component { ) } + getNodeId(node) { + return node.id; + } + isLinkSelected(link) { return false; } @@ -224,20 +279,39 @@ class Dataset extends React.Component { // linkDirectionalParticles={link => this.state.particlePercent * link.value / 100} linkDirectionalParticleSpeed={link => link.value * 0.001} cooldownTicks={this.state.enableStatic ? 0 : Infinity} + onNodeClick={(node, event) => { + if (this.state.selectedId !== this.getNodeId(node)) { + this.setState({ + selectedType: "节点", + selectedId: this.getNodeId(node), + selectedIds: this.state.graph.nodes.filter(n => (n.tag === node.tag)), + }); + } else { + this.setState({ + selectedType: null, + selectedId: null, + selectedIds: [], + }); + } + }} nodeCanvasObject={(node, ctx, globalScale) => { - let label = node.id; // const fontSize = 12 / globalScale; // ctx.font = `${fontSize}px Sans-Serif`; // const textWidth = ctx.measureText(label).width; // ctx.fillRect(node.x - bckgDimensions[0] / 2, node.y - bckgDimensions[1] / 2, ...bckgDimensions); - // if (this.isNodeSelected(node)) { - // ctx.beginPath(); - // ctx.arc(node.x, node.y, node.val * 1.4, 0, 2 * Math.PI, false); - // ctx.fillStyle = 'red'; - // ctx.fill(); - // } + if (this.state.selectedId === node.id) { + ctx.beginPath(); + ctx.arc(node.x, node.y, node.val * 1.7, 0, 2 * Math.PI, false); + ctx.fillStyle = 'red'; + ctx.fill(); + } else if (this.state.selectedIds.filter(n => n.id === node.id).length > 0) { + ctx.beginPath(); + ctx.arc(node.x, node.y, node.val * 1.4, 0, 2 * Math.PI, false); + ctx.fillStyle = 'red'; + ctx.fill(); + } ctx.beginPath(); ctx.fillStyle = node.color;