【问题标题】:Can't create links between circles after appending new circles in d3.js在 d3.js 中附加新圈子后无法在圈子之间创建链接
【发布时间】:2017-09-17 12:19:03
【问题描述】:

首先需要说,我对 d3.js 完全陌生(我使用的是版本 4)。现在我已经嵌套了节点对象,并在单击父元素后尝试绘制子元素。它部分起作用:我可以绘制子节点,但不能绘制从父圈到子圈的链接。我有这个错误:

错误:缺少:哺乳动物

TypeError:无法在字符串“哺乳动物”上创建属性“vx”

看起来source 已成功创建,但target 在第一个链接和其他链接处中断:

我不确定问题出在哪里,所以我用我现在拥有的所有代码创建了一个小提琴:https://jsfiddle.net/L6c6pxrv/4/

@KEKUATAN 建议我将新数组分配给links,不要推送每个项目。结果是:https://jsfiddle.net/L6c6pxrv/3/。没有错误了,但看起来链接仍然不知道源和目标的坐标。

这是我在点击圆圈后想要实现的目标(这里我使用的是实心节点数组,并且从一开始就定义了链接):https://jsfiddle.net/L6c6pxrv/2/

感谢您的帮助!

【问题讨论】:

  • 如何在 jsfindle 上控制台登录
  • @KEKUATAN,常规的console.log()正在开发jsfiddle,你可以在开发者工具->控制台中看到日志
  • 你不需要 forEach>push 只需要写 newLinks=links,它会昏昏沉沉,但不会被线连接,idk 但我希望这会给你灵感
  • @KEKUATAN,谢谢,这样没有报错,但是链接还是不连圈,不知道为什么=(
  • d3.selectAll('line.link') .attr('x1', function (link) { console.log(link);return link.source.x }) 你会发现有没有 source.x 和 source.y,我知道为什么以前从不使用这个图表,告诉我你是否知道一些

标签: d3.js


【解决方案1】:

请问您是否需要解释,如果可以的话我会尝试,但现在不行,我必须回家

就像我之前说的 d3 上的每个图表在制作之前首先要了解结构,了解这个结构图表,如果你在工作的 findle 上看到数据数组,你会看到没有子对象和 id 或源在 2 个数组之间相同的值。 我假设您的数据在 2 个数据数组、id 和源之间没有相同的数据值,这就是您拥有的原因

错误:缺少:哺乳动物

我将丢失的哺乳动物添加到子对象中

如果你控制台节点和链接,你会发现这个图表类型生成 vx 和 vy

TypeError:无法在字符串“哺乳动物”上创建属性“vx”

是一个连锁错误,因为没有哺乳动物,所以他们不能在 id = 哺乳动物上生成 vx 和 vy

错误:

我无法在节点中间制作“M”文本,像其他人一样跳舞。

注意:

d3.forceSimulation() 和 d3.forceLink() 我认为这是创建这样的图表的核心,这就是他们生成 cildren 或 vx 和 vy 的原因

提示:

确保链接数据和节点数据具有相同的值,如 id 和源,这样你就会得到连接,不要相信我这只是分享我所知道的,而不是我所知道的,尝试有更好的老师更好地理解

var nodes = [
        {
            id: "mammal",
            label: "Mammals",
            fill: 'orange',
            color: '#333333',
            children: [
                        {
                    id: "mammal",
                    label: "Dogs",
                    fill: 'yellow',
                    color: 'orangered'
                },
                {
                    id: "dog",
                    label: "Dogs",
                    fill: 'yellow',
                    color: 'orangered'
                },
                {
                    id: "cat",
                    label: "Cats",
                    fill: 'white',
                    color: 'blue'
                },
                {
                    id: "fox",
                    label: "Foxes",
                    fill: 'green',
                    color: 'black'
                },
                {
                    id: "elk",
                    label: "Elk",
                    fill: 'black',
                    color: 'orangered'
                },
                {
                    id: "insect",
                    label: "Insects",
                    fill: '#333333',
                    color: 'lightblue',
                    children: [
                        {
                            id: "pike",
                            label: "Pikes",
                            fill: 'white',
                            color: 'forestgreen'
                        }
                    ]
                },
                {
                    id: "ant",
                    label: "Ants",
                    fill: 'violet',
                    color: 'white'
                },
                {
                    id: "bee",
                    label: "Bees",
                    fill: 'white',
                    color: 'purple'
                },
                {
                    id: "fish",
                    label: "Fish",
                    fill: 'darkblue',
                    color: 'white'
                },
                {
                    id: "carp",
                    label: "Carp",
                    fill: 'purple',
                    color: 'white'
                }
            ]
        }
    ];

    var links = [
        // { target: "mammal", source: "dog" },
        // { target: "mammal", source: "cat" },
        // { target: "mammal", source: "fox" },
        // { target: "mammal", source: "elk" },
        // { target: "mammal", source: "insect" },
        // { target: "mammal", source: "ant" },
        // { target: "mammal", source: "bee" },
        // { target: "mammal", source: "fish" },
        // { target: "mammal", source: "carp" }
        // { target: "insect", source: "pike" }
    ];



    var width = window.innerWidth;
    var height = window.innerHeight;

    var svg = d3.select('svg');

    // Append rect and make it draggable
    svg.append('rect').style('width', width * 2).style('height', height * 2).style('fill', 'transparent');
    var dragcontainer = d3.drag()
        .on("drag", function(d) {
            d3.select(this).attr("transform", "translate(" + (d.x = d3.event.x) + "," + (d.y = d3.event.y) + ")");
        });
    var g = d3.select('svg').select("g").datum({x: 0, y: 0}).call(dragcontainer);

    var groupWrapper = svg.append('g');



    // Zoom
    var zoom = d3.zoom()
        .scaleExtent([-Infinity, 100])
        .on('zoom', zoomFn);

    function zoomFn() {
        d3.select('svg').select('g')
            .attr('transform', 'translate(' + d3.event.transform.x + ',' + d3.event.transform.y + ') scale(' + d3.event.transform.k + ')');
    }

    d3.select('svg').call(zoom);



    // simulation setup with all forces
    var linkForce = d3
        .forceLink()
        .id(function (link) { return link.id })
        .strength(function (link) { return 0.3 });

    var simulation = d3
        .forceSimulation()
        .force('link', linkForce)
        .force('charge', d3.forceManyBody().strength(-5000))
        .force('center', d3.forceCenter(width / 2, height / 2));

    var dragDrop = d3.drag().on('start', function (node) {
        node.fx = node.x;
        node.fy = node.y;
    }).on('drag', function (node) {
        simulation.alphaTarget(0.7).restart();
        node.fx = d3.event.x;
        node.fy = d3.event.y;
    }).on('end', function (node) {
        if (!d3.event.active) {
            simulation.alphaTarget(0);
        }
        node.fx = null;
        node.fy = null;
    });



    var linkElements = groupWrapper.append("g")
        .attr("class", "links")
        /**
         * comment below
         */
        .selectAll("line")
        .data(links)
        .enter().append("line")
        .attr("stroke-width", 1)
        .attr("stroke", "rgba(50, 50, 50, 0.2)");

    var nodeElementsWrapper = groupWrapper.append("g").attr('class', '1');

    var nodeElementsGroup = nodeElementsWrapper
        .attr("class", "nodes")
        .selectAll("circle")
        .data(nodes)
        .enter().append("g")
        .attr('class', 'item')
        .on("click", function(d) {
            console.log("on click", d);
            draw();
        });

    var circleElements = nodeElementsGroup
        .append("circle")
        .attr("r", 100)
        .attr("fill", function(item) {
            return item.fill;
        })
        .attr("stroke", function(item) {
            return item.color;
        })
        .attr("stroke-width", function(item) {

        })
        .call(dragDrop);

    var textElements = d3.selectAll('g.item')
        .each(function(item, i) {
            d3.select(this)
                .append('text')
                .attr("font-size", 50)
                .attr("text-anchor", "middle")
                .attr("alignment-baseline", "central")
                .attr("fill", function () { return item.color })
                .text(function () { return item.id[0].toUpperCase() })

        });



    // Draw children
    function draw() {
        var newLinks = [
            { target: "mammal", source: "dog" },
            { target: "mammal", source: "cat" },
            { target: "mammal", source: "fox" },
            { target: "mammal", source: "elk" },
            { target: "mammal", source: "insect" },
            { target: "mammal", source: "ant" },
            { target: "mammal", source: "bee" },
            { target: "mammal", source: "fish" },
            { target: "mammal", source: "carp" }
        ];

        newLinks.forEach(function(item) {
            links.push(item);
        });

        console.log('LINKS: ', links);

        nodeElementsGroup = nodeElementsWrapper
            .attr("class", "nodes")
            .selectAll("circle")
            .data(nodes[0].children)
            .enter().append("g")
            .attr('class', 'item')
            .on("click", function(d) {
                console.log("on click", d);
            });

        circleElements = nodeElementsGroup
            .data(nodes[0].children)
            .append("circle")
            .attr("r", 100)
            .attr("fill", function(item) {
                return item.fill;
            })
            .attr("stroke", function(item) {
                return item.color;
            })
            .attr("stroke-width", function(item) {

            })
            .call(dragDrop);

        textElements = d3.selectAll('g.item')
            .each(function(item, i) {
            var t = d3.select(this).text()
            if (t=='M'){

            }else{
                d3.select(this)

                    .append('text')
                    .attr("font-size", 50)
                    .attr("text-anchor", "middle")
                    .attr("alignment-baseline", "central")
                    .attr("fill", function () { return item.color })
                    .text(function () { 
                    var s =  item.id[0].toUpperCase()       
                    if (s!=='M'){
                    return s
                                        }
                    }).call(dragDrop)
          }
            })          


        linkElements = d3.select('g.links')
            .attr("class", "links")
            .selectAll("line")
            .data(links)
            .enter().append("line")
            .attr("class", "link")
            .attr("stroke-width", 1)
            .attr("stroke", "rgba(50, 50, 50, 0.2)");

        // simulation
        simulation.nodes(nodes[0].children).on('tick', function() {
            d3.selectAll('circle')
                .attr('cx', function (node) { return node.x })
                .attr('cy', function (node) { return node.y });
            d3.selectAll('text')
                .attr('x', function (node) { return node.x })
                .attr('y', function (node) { return node.y });
            d3.selectAll('line.link')
                .attr('x1', function (link) { return link.source.x })
                .attr('y1', function (link) { return link.source.y })
                .attr('x2', function (link) { return link.target.x })
                .attr('y2', function (link) { return link.target.y })
        });

     //   simulation.force("link").links(d3.selectAll('line.link')); // "links" instead of d3.selectAll('line.link')
    }



    // Simulation
    simulation.nodes(nodes).on('tick', function() {
        circleElements
            .attr('cx', function (node) { return node.x })
            .attr('cy', function (node) { return node.y });
        d3.selectAll('text')
            .attr('x', function (node) { return node.x })
            .attr('y', function (node) { return node.y });
        linkElements
            .attr('x1', function (link) { return link.source.x })
            .attr('y1', function (link) { return link.source.y })
            .attr('x2', function (link) { return link.target.x })
            .attr('y2', function (link) { return link.target.y })
    });

    simulation.force("link").links(links);
html {
  background-color: gray;
}

body {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

svg {
  position: fixed;
  top: 0;
  width: auto;
  height: auto;
  min-width: 100%;
  min-height: 100%;
  background-color: gray;
}

circle {
  cursor: pointer;
}

text {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -o-user-select: none;
  user-select: none;
  cursor: pointer;
}

line {
  stroke: #fff;
  stroke-width: 1.5;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
  
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<svg></svg>
</body>
</html>

【讨论】:

  • 非常感谢这个解决方案,它完美运行!但是如果你能解释你做了什么,那对我真的很有帮助,我是 d3.js 世界的新手
  • 我的英语不好,对不起
  • 我的英文也是,没关系。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-26
  • 1970-01-01
  • 2012-08-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
相关资源
最近更新 更多