Reputation: 341
I am trying to run the attached code with a local JSON file. So far the data was in the HTMLand works as expected. I tried several solutions from stackoverflow. My latest attempt was the visual code extension "live server" which loads but without any data or d3 code. Further my firefox settings allow external file import as well as chrome. Still not working. :/
Obviously I am doing it wrong. I would appreciate if somebody could guide me.
{
"nodes": [
{ "id": 0, "active": true, "state": "on" },
{ "id": 1, "active": true, "state": "on" },
{ "id": 2, "active": true, "state": "on" },
{ "id": 3, "active": true, "state": "on" },
{ "id": 4, "active": true, "state": "on" },
{ "id": 5, "active": true, "state": "on" },
{ "id": 6, "active": true, "state": "on" },
{ "id": 7, "active": true, "state": "on" },
{ "id": 8, "active": true, "state": "on" }
],
"links": [
{ "source": 0, "target": 1},
{ "source": 0, "target": 2},
{ "source": 0, "target": 3},
{ "source": 1, "target": 7},
{ "source": 1, "target": 6},
{ "source": 1, "target": 8},
{ "source": 2, "target": 4},
{ "source": 2, "target": 5}
]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>stackoverflow demo</title>
<script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<style>
body {
background-color: #e6e7ee;
}
circle {
stroke: black;
stroke-width: 1px;
cursor: pointer;
}
</style>
<body>
<script>
/*
var graph = {
"nodes": [
{ "id": 0, "active": true, "state": "on" },
{ "id": 1, "active": true, "state": "on" },
{ "id": 2, "active": true, "state": "on" },
{ "id": 3, "active": true, "state": "on" },
{ "id": 4, "active": true, "state": "on" },
{ "id": 5, "active": true, "state": "on" },
{ "id": 6, "active": true, "state": "on" },
{ "id": 7, "active": true, "state": "on" },
{ "id": 8, "active": true, "state": "on" },
],
"links": [
{ "source": 0, "target": 1},
{ "source": 0, "target": 2},
{ "source": 0, "target": 3},
{ "source": 1, "target": 7},
{ "source": 1, "target": 6},
{ "source": 1, "target": 8},
{ "source": 2, "target": 4},
{ "source": 2, "target": 5},
]
}
*/
d3.json("data.json", function (error, graph) {
if (error) throw error
var svg = d3.select("body").append("svg")
.attr("width", window.innerWidth)
.attr("height", window.innerHeight)
.attr("class", "svg")
.call(d3.zoom().on("zoom", function (event) {
svg.attr("transform", event.transform)
}))
.append("g")
d3.select("svg").on("dblclick.zoom", null)
// append markers to svg
svg.append("defs").append("marker")
.attr("id", "arrowhead")
.attr("viewBox", "-0 -5 10 10")
.attr("refX", 6)
.attr("refY", 0)
.attr("orient", "auto")
.attr("markerWidth", 100)
.attr("markerHeight", 100)
.attr("xoverflow", "visible")
.append("svg:path")
.attr("d", "M 0,-1 L 2 ,0 L 0,1")
.attr("fill", "red")
.style("stroke", "none")
var linkContainer = svg.append("g").attr("class", "linkContainer")
var nodeContainer = svg.append("g").attr("class", "nodeContainer")
var forceLayout = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) {
return d.id;
}).distance(125))
.force("charge", d3.forceManyBody().strength(-1250))
.force("center", d3.forceCenter(window.innerWidth / 2, window.innerHeight / 2))
.force("collision", d3.forceCollide().radius(50))
//###############################################
//################## initialize #################
//###############################################
function init() {
links = linkContainer.selectAll(".link")
.data(graph.links)
.join("line")
.attr("class", "link")
.attr('marker-end', 'url(#arrowhead)')
.style("stroke", "black")
nodes = nodeContainer.selectAll(".node")
.data(graph.nodes, function (d) { return d.id; })
.join("g")
.attr("class", "node")
.attr("id", function (d) { return "node" + d.id; })
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded)
)
nodes.selectAll("circle")
.data(d => [d])
.join("circle")
.attr("r", 40)
.style("fill", setColor)
.on("click", switchState)
nodes.selectAll("text")
.data(d => [d])
.join("text")
.attr("dominant-baseline", "central")
.attr("text-anchor", "middle")
.attr("id", function (d) { return "text" + d.id })
.attr("pointer-events", "none")
.text(function (d) {
return d.id + " - " + d.state
})
forceLayout
.nodes(graph.nodes)
.on("tick", outerTick)
forceLayout
.force("link")
.links(graph.links)
}
//###############################################
//##### set color in relation of the state ######
//###############################################
function setColor(d) {
switch (d.state) {
case "on":
return "greenyellow"
case "limited":
return "yellow"
case "error":
return "red"
case "off":
return "grey"
default:
return "greenyellow"
}
}
//###############################################
//######## switch state - turn off & on #########
//###############################################
function switchState(event, d) {
if (d.active == true) {
d.active = false
d.state = "off"
} else if (d.active == false) {
d.active = true
d.state = "on"
}
}
function outerTick() {
links
.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;
});
nodes.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
function dragStarted(event, d) {
if (!event.active) forceLayout.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragEnded(event, d) {
if (!event.active) forceLayout.alphaTarget(0);
d.fx = undefined;
d.fy = undefined;
}
})
</script>
</body>
</html>
Upvotes: 0
Views: 1485
Reputation: 7210
In D3 V6 the d3.json
function should be used as a Promise:
d3.json(url).then(onLoad).catch(err => console.log(err));
See the snippet below:
const url = "https://api.jsonbin.io/b/60a62c6265d5d77ffc89cdca";
const onLoad = graph => {
console.log('G: ', graph);
var svg = d3.select("svg")
.call(d3.zoom().on("zoom", function (event) {
svg.attr("transform", event.transform)
}))
.append("g")
d3.select("svg").on("dblclick.zoom", null)
// append markers to svg
svg.append("defs").append("marker")
.attr("id", "arrowhead")
.attr("viewBox", "-0 -5 10 10")
.attr("refX", 6)
.attr("refY", 0)
.attr("orient", "auto")
.attr("markerWidth", 100)
.attr("markerHeight", 100)
.attr("xoverflow", "visible")
.append("svg:path")
.attr("d", "M 0,-1 L 2 ,0 L 0,1")
.attr("fill", "red")
.style("stroke", "none")
var linkContainer = svg.append("g").attr("class", "linkContainer")
var nodeContainer = svg.append("g").attr("class", "nodeContainer")
var forceLayout = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) {
return d.id;
}).distance(125))
.force("charge", d3.forceManyBody().strength(-1250))
.force("center", d3.forceCenter(window.innerWidth / 2, window.innerHeight / 2))
.force("collision", d3.forceCollide().radius(50))
init();
//###############################################
//################## initialize #################
//###############################################
function init() {
links = linkContainer.selectAll(".link")
.data(graph.links)
.join("line")
.attr("class", "link")
.attr('marker-end', 'url(#arrowhead)')
.style("stroke", "black")
nodes = nodeContainer.selectAll(".node")
.data(graph.nodes, function (d) { return d.id; })
.join("g")
.attr("class", "node")
.attr("id", function (d) { return "node" + d.id; })
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded)
)
nodes.selectAll("circle")
.data(d => [d])
.join("circle")
.attr("r", 40)
.style("fill", setColor)
.on("click", switchState)
nodes.selectAll("text")
.data(d => [d])
.join("text")
.attr("dominant-baseline", "central")
.attr("text-anchor", "middle")
.attr("id", function (d) { return "text" + d.id })
.attr("pointer-events", "none")
.text(function (d) {
return d.id + " - " + d.state
})
forceLayout
.nodes(graph.nodes)
.on("tick", outerTick)
forceLayout
.force("link")
.links(graph.links)
}
//###############################################
//##### set color in relation of the state ######
//###############################################
function setColor(d) {
switch (d.state) {
case "on":
return "greenyellow"
case "limited":
return "yellow"
case "error":
return "red"
case "off":
return "grey"
default:
return "greenyellow"
}
}
//###############################################
//######## switch state - turn off & on #########
//###############################################
function switchState(event, d) {
if (d.active == true) {
d.active = false
d.state = "off"
} else if (d.active == false) {
d.active = true
d.state = "on"
}
}
function outerTick() {
links
.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;
});
nodes.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
function dragStarted(event, d) {
if (!event.active) forceLayout.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragEnded(event, d) {
if (!event.active) forceLayout.alphaTarget(0);
d.fx = undefined;
d.fy = undefined;
}
};
d3.json(url).then(onLoad).catch(err => console.log(err));
body {
background-color: #e6e7ee;
}
circle {
stroke: black;
stroke-width: 1px;
cursor: pointer;
}
<script src="https://d3js.org/d3.v6.min.js"></script>
<svg width="1000" height="1000" />
Upvotes: 2