该程序的目标是显示图形并根据顶点的数量 n 为其着色。着色的规则是:
n = 3->颜色为绿色
n = 5->红色
n不等于3或5->不执行任何操作
其他规则:如果顶点名称=“ 2”,则该顶点将被着色为黄色。
图形数据存储在文本文件中。它们与项目位于同一文件夹中。这是两个文件。
GraphN3.txt:
p edge 3 3
e 1 2
e 2 1
e 1 3
e 2 3
GraphN5.txt:
p edge 5 5
e 87 88
e 88 89
e 89 90
e 90 91
e 91 87
文件中的第一行未处理,但是总是可以预期的。 重要说明:每个文件的末尾都有行尾(输入键)。
D3.js在项目中用于受力定向图。 “ browseFile”输入使我可以选择要显示的图形。 “运行着色”根据着色规则为显示的图形着色。
我遇到的麻烦是: 我只为打开的第一个图形文件得到正确的颜色。 任何继续打开文件都不会导致着色。
重新加载浏览器后,将发生着色。 我希望能够无需打开浏览器就可以多次打开和绘制彩色图。 html代码:
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<script
src="https://code.jquery.com/jquery-3.2.1.js"
integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE="
crossorigin="anonymous"></script>
<meta charset="utf-8">
<title>Force Directed Graph</title>
</head>
<body>
<input type='file' id="browseFile" >
<button onclick="runColoring()">run coloring </button>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="graphScript.js"></script>
</body>
'graphScript.js'代码:
class Graph {
constructor()
{
this.vertexNeighbours = new Map();
this.nodes_data = [];
this.links_data = [];
}
createVertex(v)
{
var alreadyExisting = false;
var get_keys = this.vertexNeighbours.keys();
for (var i of get_keys)
{
// if true - the vertex already existed and should not be added
if(i.toString().trim() == v.toString().trim())
{
alreadyExisting = true;
break
}
}
if (alreadyExisting == false)
{
// nodes_data update
this.nodes_data.push({"name": v});
// vertex neighbours list
this.vertexNeighbours.set(v, []);
}
}
createEdge(v, w)
{
var alreadyExisting = false;
var get_keys = this.vertexNeighbours.keys();
for (var i of get_keys)
{
if(i.toString().trim() == v.toString().trim())
{
var get_values = this.vertexNeighbours.get(i);
for (var j of get_values)
{
// if true - the edge already existed and should not be added
if(j.toString().trim() == w.toString().trim())
{
alreadyExisting = true;
break
}
}
}
}
if (alreadyExisting == false)
{
this.links_data.push({"source":v,"target":w});
this.vertexNeighbours.get(v).push(w);
this.vertexNeighbours.get(w).push(v);
}
}
colorVertices()
{
var VerticesColor = "";
var get_keys = this.vertexNeighbours.keys();
var keysQuant = 0;
for(var i of get_keys)
{
keysQuant++;
}
if (keysQuant == 3 )
{
VerticesColor = "green";
}
if (keysQuant == 5)
{
VerticesColor = "red";
}
svg.select("g")
.attr("class", "nodes")
.selectAll("circle")
.style("fill", function(d) {
if (d.name == "2") {
return "yellow";
}
else
return VerticesColor;
});
}
}
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var gr = new Graph();
var input = document.getElementById('browseFile');
function runColoring()
{
gr.colorVertices();
}
input.onchange= function fileOpening() { //myFunction na klikniecie 'Try it' uruchamia wczytywanie danych
var filePath = document.getElementById("browseFile").files[0].name;
$.get(filePath, function (graphData) {
console.log(graphData);
gr = new Graph();
gr.nodes_data = [];
gr.links_data = [];
d3.selectAll("g > *").remove();
var splittedLines = graphData.split('\n');
var j = 0;
while (splittedLines[j+1] != null && splittedLines[j+2] != undefined)
{
var dataLines = splittedLines[j+1].split(" ");
gr.createVertex(dataLines[1].trim());
gr.createVertex(dataLines[2].trim());
j++;
}
j = 0;
while (splittedLines[j+1] != null && splittedLines[j+2] != undefined)
{
dataLines = splittedLines[j+1].split(" ");
gr.createEdge(dataLines[1].trim(),dataLines[2].trim());
j++;
}
var nodes_data = gr.nodes_data;
//Create links data
var links_data = gr.links_data;
var radius = 9;
//set up the simulation and add forces
var simulation = d3.forceSimulation()
.nodes(nodes_data);
var link_force = d3.forceLink(links_data)
.id(function(d) { return d.name; });
var charge_force = d3.forceManyBody()
.strength(-100);
var center_force = d3.forceCenter(width / 2, height / 2);
simulation
.force("charge_force", charge_force)
.force("center_force", center_force)
.force("links",link_force)
;
//add tick instructions:
simulation.on("tick", tickActions );
//add encompassing group for the zoom
var g = svg.append("g")
.attr("class", "everything");
//draw lines for the links
var link = g.append("g")
.attr("class", "links")
.selectAll("line")
.data(links_data)
.enter().append("line")
.attr("stroke-width", 2)
.style("stroke", linkColour);
//draw circles for the nodes
var node = g.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(nodes_data)
.enter()
.append("circle")
.attr("r", radius);
// .attr("fill", circleColour);
//add drag capabilities
var drag_handler = d3.drag()
.on("start", drag_start)
.on("drag", drag_drag)
.on("end", drag_end);
drag_handler(node);
//add zoom capabilities
var zoom_handler = d3.zoom()
.on("zoom", zoom_actions);
zoom_handler(svg);
/** Functions **/
//Function to choose the line colour
function linkColour(d){
return "red";
}
//Drag functions
//d is the node
function drag_start(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
//make sure you can't drag the circle outside the box
function drag_drag(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function drag_end(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
//Zoom functions
function zoom_actions(){
g.attr("transform", d3.event.transform)
}
function tickActions() {
//update circle positions each tick of the simulation
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
//update link positions
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
}
}
)
};