【问题标题】:run d3.js with local JSON file使用本地 JSON 文件运行 d3.js
【发布时间】:2021-08-09 12:53:42
【问题描述】:

我正在尝试使用本地 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>

【问题讨论】:

    标签: javascript json d3.js


    【解决方案1】:

    在 D3 V6 中,d3.json 函数应该用作 Promise:

    d3.json(url).then(onLoad).catch(err => console.log(err));
    

    参见下面的 sn-p:

    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" />

    【讨论】:

    • 意味着网络服务器是强制性的?因为无法输入本地路径。
    • @ICoded - 如果您使用 VS 代码和“实时服务器”功能,您可以使用 d3.json("./data.json").then(... - 您需要前面的 ./
    • 它应该是任何类型的有效 URL(相对于根或全局的本地)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多