D3:如何在Groups of Force布局节点上绘制多个凸包?

2024-05-08

我试图在力布局中的所有组上绘制凸包。但我只画出了一半的凸包。当 D3 尝试绘制其余的船体时,控制台返回错误:元素尚未创建。然而,当我检查控制台中的“groups”变量时,所有组数据都在那里,x、y 数据都设置得很好。见下图:

我什至尝试在tick函数中延迟船体的绘制,但它仍然不起作用并且我得到了相同的结果(如下图所示)。

JSFiddle:只得到了一半。我想要的凸包 https://jsfiddle.net/v6b9bwbm/1/

这是代码:

<script>
    var radius = 5.5;
    var color = d3.scaleOrdinal(d3.schemeCategory20b);
    var scale = d3.scaleLinear()
        .domain([0.5, 1])
        .range([1.8, 3.8]);
    var svg2 = d3.select("#svg2");
    var w = +svg2.attr("width"),
        h = +svg2.attr("height");
    var hull = svg2.append("path")
        .attr("class", "hull");
    var groupPath = function(d) { return "M" + d3.polygonHull(d.values.map(function(i) { return [i.x, i.y]; }))
        .join("L") + "Z"; };

    function ticked() {
        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;
            });

        fnode
            .attr("cx", function (d) {
                return d.x = Math.max(radius, Math.min(w - radius, d.x));
            })
            .attr("cy", function (d) {
                return d.y = Math.max(radius, Math.min(h - radius, d.y));
            })
            .attr("r", radius);

        delayHull(6000);

    }

    function delayHull(delay) {
        setTimeout(function() {
            svg2.selectAll("path")
                .data(groups)
                .attr("d", groupPath)
                .enter()
                .append("path")
                .attr("class", "hull")
                .attr("d", groupPath);

        }, delay);
    }

    var simulation, link, fnode, groups;

    var fnodeg = svg2.append("g")
        .attr("class", "fnode");

    var linkg = svg2.append("g")
        .attr("class", "links")
        .attr("id", "linkg");

    d3.json("..//vizData//forceLayout//forceLayout_15000.json", function(error, graph) {
        if (error) throw error;
        simulation = d3.forceSimulation()
            .force("link", d3.forceLink().id(function (d) {
                return d.id;
            }).distance(30).strength(1))
            .force("charge", d3.forceManyBody().strength(-2).distanceMin(15).distanceMax(180))
            .force("center", d3.forceCenter(w / 2, h / 2))
            .force("collide", d3.forceCollide().strength(1).iterations(2));

        link = linkg.selectAll("line")
            .data(graph.links)
            .enter().append("line")
            .attr("stroke-width", function (d) {
                return scale(d.value);
            });

        fnode = fnodeg.selectAll("circle")
            .data(graph.nodes)
            .enter().append("circle")
            .attr("r", radius)
            .attr("fill", function (d) {
                return color(d.truth);
            });

        simulation
            .nodes(graph.nodes);

        simulation.force("link")
            .links(graph.links);

        groups = d3.nest().key(function(d) { return d.group; }).entries(graph.nodes);

        simulation.on("tick", ticked);

        fnode.append("title")
            .text(function (d) { return d.id; });

        link.append("title")
            .text(function (d) { return d.value; });

    })
</script>

我参考了这个http://bl.ocks.org/donaldh/2920551 http://bl.ocks.org/donaldh/2920551凸包示例;他在tick函数之外设置了他的“groups”变量,并且没问题。

我究竟做错了什么???


建立在安德鲁的回答 https://stackoverflow.com/a/45930257/5768908,当您的集群只有两个点时,您可以简单地推送另一个内部数组:

if (d.values.length === 2) {
    var arr = d.values.map(function(i) {
        return [i.x, i.y];
    })
    arr.push([arr[0][0], arr[0][1]]);
    return "M" + d3.polygonHull(arr).join("L") + "Z";

这是您的代码,仅进行了更改:

        var radius = 5.5;
        var color = d3.scaleOrdinal(d3.schemeCategory20b);
        var scale = d3.scaleLinear()
          .domain([0.5, 1])
          .range([1.8, 3.8]);
        var svg2 = d3.select("#svg2");
        var w = +svg2.attr("width"),
          h = +svg2.attr("height");
        var hull = svg2.append("path")
          .attr("class", "hull");
        var groupPath = function(d) {
          if (d.values.length === 2) {
            var arr = d.values.map(function(i) {
              return [i.x, i.y];
            })
            arr.push([arr[0][0], arr[0][1]]);
            return "M" + d3.polygonHull(arr).join("L") + "Z";
          } else {
            return "M" + d3.polygonHull(d.values.map(function(i) {
                return [i.x, i.y];
              }))
              .join("L") + "Z";
          }
        };

        function ticked() {
          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;
            });

          fnode
            .attr("cx", function(d) {
              return d.x = Math.max(radius, Math.min(w - radius, d.x));
            })
            .attr("cy", function(d) {
              return d.y = Math.max(radius, Math.min(h - radius, d.y));
            })
            .attr("r", radius);

          delayHull(1000);

        }

        function delayHull(delay) {
          setTimeout(function() {
            svg2.selectAll("path")
              .data(groups)
              .attr("d", groupPath)
              .enter()
              .append("path")
              .attr("class", "hull")
              .attr("d", groupPath);

          }, delay);
        }

        var simulation, link, fnode, groups;

        var fnodeg = svg2.append("g")
          .attr("class", "fnode");

        var linkg = svg2.append("g")
          .attr("class", "links")
          .attr("id", "linkg");

        d3.json('https://api.myjson.com/bins/bkzxh', function(error, graph) {
          if (error) throw error;
          simulation = d3.forceSimulation()
            .force("link", d3.forceLink().id(function(d) {
              return d.id;
            }).distance(30).strength(1))
            .force("charge", d3.forceManyBody().strength(-2).distanceMin(15).distanceMax(180))
            .force("center", d3.forceCenter(w / 2, h / 2))
            .force("collide", d3.forceCollide().strength(1).iterations(2));

          link = linkg.selectAll("line")
            .data(graph.links)
            .enter().append("line")
            .attr("stroke-width", function(d) {
              return scale(d.value);
            });

          fnode = fnodeg.selectAll("circle")
            .data(graph.nodes)
            .enter().append("circle")
            .attr("r", radius)
            .attr("fill", function(d) {
              return color(d.truth);
            });

          simulation
            .nodes(graph.nodes);

          simulation.force("link")
            .links(graph.links);

          groups = d3.nest().key(function(d) {
            return d.group;
          }).entries(graph.nodes);

          simulation.on("tick", ticked);

          fnode.append("title")
            .text(function(d) {
              return d.id;
            });

          link.append("title")
            .text(function(d) {
              return d.value;
            });

        });
.links line {
  stroke: #999;
  stroke-opacity: 0.8;
}

.fnode circle {
  stroke: #fff;
  stroke-width: 1.5px;
  fill-opacity: 1;
}

.hull {
  fill: steelblue;
  stroke: steelblue;
  fill-opacity: 0.3;
  stroke-opacity: 0.3;
  stroke-width: 10px;
  stroke-linejoin: round;
}
<script src="https://d3js.org/d3.v4.js"></script>
<svg id="svg2" width="600" height="600" style="margin-left: -5px"></svg>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

D3:如何在Groups of Force布局节点上绘制多个凸包? 的相关文章

  • AJAX 安全问题

    我希望能够解决一些关于 AJAX 安全性的问题 这是我试图理解的一个场景 假设我正在使用 AJAX 向页面请求一些半敏感材料 例如 我将把用户的 ID 传递给一个 php 文件 并返回一些关于他们自己的信息 现在 是什么阻止人们模拟此 Ja
  • 检测单选按钮/复选框状态的变化

    我需要可靠地检测页面上单选按钮 复选框的状态变化 以便查看表单是否被修改 现在 这是一个完全独立的脚本 我无法修改任何控制表单的内容 目前 我只能看到两种方法 onchange事件处理程序 有助于处理文本框 文本区域和选择 但不会针对复选框
  • 当内部元素滚动位置到达顶部/底部时防止父元素滚动?

    我有一个小 浮动工具箱 一个带有position fixed overflow auto 效果很好 但是 当在该框内滚动 使用鼠标滚轮 并到达底部或顶部时 父元素 接管 滚动请求 工具框后面的文档滚动 这很烦人 而不是用户 要求的 我正在使
  • 如何使用多个 select2 框过滤表格?

    我正在尝试使用 和多个 select2 框的类来过滤表格 表格 HTML table class table tbody tr class kanban event Austin td td tr tr class csm event Ch
  • 在 Node.js 中生成带条形码的 pdf

    我在用https github com devongovett pdfkit https github com devongovett pdfkit生成 PDF 文件 我可以简单地使用类似的方法 app get get pdf req re
  • 在节点环境中存根 jQuery.ajax (jQuery 2.x)

    我正在尝试运行一些需要存根的测试jQuery ajax 我正在使用 SinonJS 来做到这一点 它曾经与旧版本的 jQuery 1 x 一起工作得很好 var require jquery var sinon require sinon
  • 有没有办法动态更改 jqGrid 的单元格值?

    这个问题可能已经被问过很多次了 但我想知道是否可以动态更改 jqgrid 的单元格值 我基本上有一个网格 它通过 JSON 字符串加载数据 在特定列的某些行上 该值可能为 null 因此 预先知道哪个行 ID 是一个问题 然后能够将 nul
  • JavaScript 字符串中的脚本标签[重复]

    这个问题在这里已经有答案了 我遇到一个问题 即 JavaScript 中带引号的字符串内有结束脚本标记 并且它正在杀死脚本 我认为这不是预期的行为 可以在这里看到这样的示例 http jsbin com oqepe edit http js
  • jQuery:查找具有特定自定义属性的元素

    我只想找到具有特定自定义属性值的元素 例如 我想找一个div其具有属性data divNumber 6 var number 6 var myDiv data divNumber number 我尝试使用http api jquery co
  • 有没有一种方法可以在没有输入的情况下发送表单值

    假设我有以下表格
  • 如何在React Native的MapView中设置标记

    我想在React Native中的MapView上设置一个标记 但是通过官方文档找不到任何信息MapView https facebook github io react native docs mapview html content 如
  • 如何将 Ajax.BeginForm MVC 助手与 JSON 结果一起使用?

    我正在尝试使用 ASP NET MVC Ajax BeginForm 帮助程序 但不想在调用完成时使用现有的内容插入选项 相反 我想使用自定义 JavaScript 函数作为回调 这可行 但我想要的结果应该以 JSON 形式返回 不幸的是
  • onClick 处理程序在每个渲染周期触发

    我有这样的默认状态 this state selectedTab tab1 then 我的渲染方法是这样的 render const selectedTab this state return li tab1 li li tab2 li d
  • 通过 JavaScript 单击按钮/页面提交

    我想了解 asp net 框架如何知道何时单击了按钮 因此一旦收到请求 就会在服务器上触发其单击事件 我需要了解它是如何工作的 因为我想从 JavaScript 触发按钮的服务器单击事件 我能够从 JavaScript 执行页面提交 doc
  • 如何知道 .keyup() 是否是字符键(jQuery)

    如何知道 keyup 是否是字符键 jQuery input keyup function if key is a character such as a b A b c 5 3 2 etc not enter key or shift o
  • 从链接打开本地文件夹

    如何通过单击任何链接打开本地文件夹视图 我尝试了很多选择 例如 a href Open folder a or a Open folder a or a Open folder a 解决方案 启动可下载链接 以下内容适用于所有浏览器 但一如
  • 为什么 call 比 apply 快那么多?

    我想知道是否有人知道why call比apply 在 Chrome 中 速度大约快 4 倍 在 Firefox 中快 30 倍 我什至可以制作自定义原型 apply2 在大多数情况下 运行速度是apply 这个想法取自角度 Function
  • Three.js点击单个粒子

    In this example http jsfiddle net agqq96bq 2 您可以看到 2 个可点击的粒子 但它们都受到点击的影响 另外 我只想检测粒子上的点击 而不将它们过滤出场景 像这儿 if intersects len
  • 如何跨多个文件跨越 javascript 命名空间?

    我永远忽略了javascript 几年前我开始使用 jQuery 这样我就可以过得去 但随着我开始更多地进行 TDD 我昨天决定真正深入研究 javascript 之后可能还有咖啡脚本 在我的 ASP NET Web 窗体应用程序中 我有很
  • 将引导程序弹出框保留在视口内

    我正在尝试使用带有按钮的侧边栏创建一个菜单 每个按钮都有一个指定的包含相关数据的弹出窗口 不幸的是 其中一个弹出窗口可能包含任意数量的行 并且在某些情况下它可能部分位于视口之外 See http jsfiddle net bfd9f 1 h

随机推荐