javascript - 使用本地 JSON 文件运行 d3.js
问题描述
我正在尝试使用本地 JSON 文件运行附加代码。到目前为止,数据在 HTML 中并且按预期工作。我尝试了 stackoverflow 的几种解决方案。我最近的尝试是加载但没有任何数据或 d3 代码的可视代码扩展“实时服务器”。此外,我的 Firefox 设置允许外部文件导入以及 chrome。还是行不通。:/
显然我做错了。如果有人可以指导我,我将不胜感激。
{
"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>
解决方案
在 D3 V6 中,该d3.json
函数应用作 Promise:
d3.json(url).then(onLoad).catch(err => console.log(err));
请参阅下面的片段:
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" />
推荐阅读
- spring - spring boot 无法启动——在配置中定义一个“TopicRepository”类型的bean
- javascript - 如何在 Cascader Ant Design ReactJs 中显示子项?
- javascript - iphone 5s 不吃饼干
- javascript - 使用模板字符串附加 HTML
- angular - 我无法使用 http-server 访问页面
- java - 在我的对象数组中的某处,运行同一行代码后值会发生变化吗?
- javascript - 如何在chart.js中旋转线性图形?
- c - 如何将 RFC 3339 日期时间转换为 IST?
- c# - 用于结帐和未退回项目的多个过滤器
- amazon-s3 - 使用 Lambda 在 EMR 上运行 aws cli 命令