在版本 4 中将节点动态添加到 D3 Force Layout

2024-03-30

我正在尝试实现一个简单的力布局,其中可以动态添加和删除节点(没有链接)。我成功地在 D3 版本 3 中实现了这个概念,但我无法将其转换为版本 4。添加和更新节点后,模拟冻结,传入的圆圈绘制在 svg 的左上角。有人知道为什么会这样吗?谢谢你的帮助 :)

我的概念基于这个解决方案:将新节点添加到力导向布局 https://stackoverflow.com/questions/9539294/adding-new-nodes-to-force-directed-layout/9544595#9544595

JSFiddle:d3 v3 中的工作代码 https://jsfiddle.net/Lvkg1avo/

/* Define class */
class Planet {
  constructor(selector) {
    this.w = $(selector).innerWidth();
    this.h = $(selector).innerHeight();

    this.svg = d3.select(selector)
      .append('svg')
      .attr('width', this.w)
      .attr('height', this.h);

    this.force = d3.layout.force()
      .gravity(0.05)
      .charge(-100)
      .size([this.w, this.h]);

    this.nodes = this.force.nodes();
  }

  /* Methods (are called on object) */
  update() {
    /* Join selection to data array -> results in three new selections enter, update and exit */
    const circles = this.svg.selectAll('circle')
      .data(this.nodes, d => d.id); // arrow function, function(d) { return d.y;}

    /* Add missing elements by calling append on enter selection */
    circles.enter()
      .append('circle')
      .attr('r', 10)
      .style('fill', 'steelblue')
      .call(this.force.drag);

    /* Remove surplus elements from exit selection */
    circles.exit()
      .remove();

    this.force.on('tick', () => {
      circles.attr('cx', d => d.x)
        .attr('cy', d => d.y);
    });

    /* Restart the force layout */
    this.force.start();
  }

  addThought(content) {
    this.nodes.push({ id: content });
    this.update();
  }

  findThoughtIndex(content) {
    return this.nodes.findIndex(node => node.id === content);
  }

  removeThought(content) {
    const index = this.findThoughtIndex(content);
    if (index !== -1) {
      this.nodes.splice(index, 1);
      this.update();
    }
  }
}

/* Instantiate class planet with selector and initial data*/
const planet = new Planet('.planet');
planet.addThought('Hallo');
planet.addThought('Ballo');
planet.addThought('Yallo');

这是我将代码翻译成 v4 的意图:

/* Define class */
class Planet {
  constructor(selector) {
    this.w = $(selector).innerWidth();
    this.h = $(selector).innerHeight();

    this.svg = d3.select(selector)
      .append('svg')
      .attr('width', this.w)
      .attr('height', this.h);

    this.simulation = d3.forceSimulation()
      .force('charge', d3.forceManyBody())
      .force('center', d3.forceCenter(this.w / 2, this.h / 2));

    this.nodes = this.simulation.nodes();
  }

  /* Methods (are called on object) */
  update() {
    /* Join selection to data array -> results in three new selections enter, update and exit */
    let circles = this.svg.selectAll('circle')
      .data(this.nodes, d => d.id); // arrow function, function(d) { return d.y;}

    /* Add missing elements by calling append on enter selection */
    const circlesEnter = circles.enter()
      .append('circle')
      .attr('r', 10)
      .style('fill', 'steelblue');

    circles = circlesEnter.merge(circles);

    /* Remove surplus elements from exit selection */
    circles.exit()
      .remove();

    this.simulation.on('tick', () => {
      circles.attr('cx', d => d.x)
        .attr('cy', d => d.y);
    });

    /* Assign nodes to simulation */
    this.simulation.nodes(this.nodes);

    /* Restart the force layout */
    this.simulation.restart();
  }

  addThought(content) {
    this.nodes.push({ id: content });
    this.update();
  }

  findThoughtIndex(content) {
    return this.nodes.findIndex(node => node.id === content);
  }

  removeThought(content) {
    const index = this.findThoughtIndex(content);
    if (index !== -1) {
      this.nodes.splice(index, 1);
      this.update();
    }
  }
}

Please 参见 plunkr 示例 https://plnkr.co/edit/iadT0ikcpKELU0eaE9f6?p=info

我使用的是画布,但原理是相同的:

你必须给你的new首先将节点数组并链接到 D3 核心函数,然后再将它们添加到原始数组中。

drawData: function(graph){
  var countExtent = d3.extent(graph.nodes,function(d){return d.connections}),
      radiusScale = d3.scalePow().exponent(2).domain(countExtent).range(this.nodes.sizeRange);

      // Let D3 figure out the forces
      for(var i=0,ii=graph.nodes.length;i<ii;i++) {
        var node = graph.nodes[i];

        node.r = radiusScale(node.connections);
        node.force = this.forceScale(node);
        };

    // Concat new and old data
    this.graph.nodes = this.graph.nodes.concat(graph.nodes);
    this.graph.links = this.graph.links.concat(graph.links);

    // Feed to simulation
    this.simulation
        .nodes(this.graph.nodes);

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

    this.simulation.alpha(0.3).restart();
}

然后,告诉 D3 使用新数据重新启动。

当 D3 呼叫您时tick()函数,它已经知道您需要将什么坐标应用于 SVG 元素。

ticked: function(){
     if(!this.graph) {
        return false;
    }

    this.context.clearRect(0,0,this.width,this.height);
    this.context.save();
    this.context.translate(this.width / 2, this.height / 2);

    this.context.beginPath();
    this.graph.links.forEach((d)=>{
        this.context.moveTo(d.source.x, d.source.y);
        this.context.lineTo(d.target.x, d.target.y);
    });
    this.context.strokeStyle = this.lines.stroke.color;
    this.context.lineWidth = this.lines.stroke.thickness;

    this.context.stroke();

    this.graph.nodes.forEach((d)=>{
        this.context.beginPath();

        this.context.moveTo(d.x + d.r, d.y);
        this.context.arc(d.x, d.y, d.r, 0, 2 * Math.PI);

        this.context.fillStyle = d.colour;
        this.context.strokeStyle =this.nodes.stroke.color;
        this.context.lineWidth = this.nodes.stroke.thickness;
        this.context.fill();
        this.context.stroke();
    });

    this.context.restore();
}

笨蛋的例子 https://plnkr.co/edit/iadT0ikcpKELU0eaE9f6?p=info

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在版本 4 中将节点动态添加到 D3 Force Layout 的相关文章

  • Oo 任何 IDE 中的 javascript 代码补全

    你知道有什么IDE可以自动完成这种代码吗 我这里有一个 javascript 类生成器 function var core bind function method scope if method instanceof Function t
  • 取消html5浏览器中的单图请求

    我正在动态加载 大 图像以绘制到 html5 画布中 如下所示 var t new Image t onload t src http myurl 但每隔一段时间就会想取消图片请求完全地 我想出的唯一方法是设置src to i e t sr
  • Angular 2 链式 Promise 并传递拒绝

    应该是一个简单的问题 但是我找不到有关如何做到这一点的文档 像这样链接一个承诺 Making a promise no problem let promise new Promise resolve reject gt let data d
  • 如何在ASP.NET Webform中使用Jquery表单插件?

    我遇到了这个插件 http malsup com jquery form getting started http malsup com jquery form getting started 我想知道如何在 ASP NET WebForm
  • jquery 验证错误位置

    这看起来很简单 但我无法弄清楚 我正在使用 jquery 验证插件 我验证所有文件 但我想要的是在输入文本行中显示验证消息警报 例如在电子邮件输入中 请填写电子邮件地址 但现在它出现在所有字段下 在我的html中
  • Leaflet js虚构地图

    我是 Leaflet 的新手 我想了解如何创建完全交互式的虚构地图 我有一张图像想要转换为传单地图 该图像基本上像图表一样具有许多连接和点 我想首先将该图像转换为地图 能够将鼠标悬停在这些点上 突出显示它们并显示有关它们的信息 并且还可以在
  • 使用 CryptoJS 更改密钥 [重复]

    这个问题在这里已经有答案了 我正在使用 CryptoJS 来加密和解密文本 在这里 我只是获取消息并显示加密和解密消息 我使用DES算法进行加密和解密 这是我的 HTML 文件
  • HTML2canvas 和 Canvas2image,下载的屏幕截图不显示我的 HTML 图像

    我一直在开发一个 HTML 页面 我想将其转换为图像 我一直在使用 html2canvas 和 canvas2image 脚本并采用此代码http jsfiddle net 8ypxW 3 http jsfiddle net 8ypxW 3
  • 在闪亮的数据表中为每个单元格显示工具提示或弹出窗口?

    有没有什么方法可以为 r闪亮数据表中的每个单元格获取工具提示 有很多方法可以获取悬停行或列 但我找不到一种方法来获取行和列索引并为每个单元格显示不同的悬停工具提示 任何人都可以修改以下代码吗 library shiny library DT
  • 使用 JS 合并具有相同值的相邻 HTML 表格单元格

    我已经为此苦苦挣扎了一段时间 我有一个根据一些 JSON 数据自动生成的表 该数据可能会有所不同 我想合并第一列中具有相同值的相邻单元格 例如此表中的 鱼 和 鸟 table tr td fish td td salmon td tr tr
  • IE11不监听MSFullscreenChange事件

    我正在尝试使用 Bigscreen js 在 IE11 中使用全屏 但 IE11 不监听 MS FullscreenChange 事件 document addEventListener MSFullscreenChange functio
  • 单击关闭按钮后不显示 Google 一键登录 UI

    我正在尝试按照本指南使新的谷歌一键登录工作 https developers google com identity one tap web https developers google com identity one tap web
  • 将 javascript 整数转换为字节数组并返回

    function intFromBytes x var val 0 for var i 0 i lt x length i val x i if i lt x length 1 val val lt lt 8 return val func
  • 当用户单击链接时,如何记录 MixPanel 事件?

    当用户单击某种类型的链接时 我试图在 MixPanel 中记录一个事件 我正在使用 JQuery 不引人注意地完成此操作 据我所知 我需要添加一个回调函数 以便在记录事件后将用户带到 URL 这是我正在使用的代码 不幸的是
  • Nodejs mysql 获取正确的时间戳格式

    我在用着mysqljs https github com mysqljs mysql得到结果后sql我变得不同TimeStamp格式如下 created at Sat Jul 16 2016 23 52 54 GMT 0430 IRDT 但
  • JavaScript onresize 事件多次触发

    我在尝试仅在触发 onresize 事件时运行一次函数时遇到一些麻烦 我已经看过这个问题DOM onresize 事件 https stackoverflow com questions 1500312 javascript onresiz
  • Jquery - 通过在字符串中构建 id 的 id 获取元素

    我在使用 jquery 元素时遇到问题 我正在 var 中构造名称 例如 var myId myGotId myId attr title changed myId 返回空 我想通过 id 获取我的元素 但动态构建我的 Id 连接字符串 编
  • 在 Javascript 中减少/分组数组

    基于this https stackoverflow com a 40774906 3254598例如 我想以稍微不同的方式按对象进行分组 结果应该如下 key audi items make audi model r8 year 2012
  • 如何在 gulp.src 中使用基本正则表达式?

    我正在尝试选择两个文件gulp src highcharts js and highcharts src js 当然 我知道我可以使用数组表达式显式添加这两个表达式 但出于学习目的 我尝试为它们编写一个表达式 我读过可以使用简单的正则表达式
  • 在 GWT 中,在任何主机页标记上添加事件处理程序

    我想为任何标签添加 MouseOver 事件处理程序 举个例子 我想为旧版 HTML 页面中的每个锚点页面添加事件处理程序 继GWT指南 http code google com webtoolkit doc 1 6 DevGuideUse

随机推荐

  • fancyBox 3 中的转换

    是否可以指定在 fancyBox 3 中使用哪个转换 我对 3 个转变感兴趣 打开幻灯片 画廊 在幻灯片之间导航 关闭幻灯片 图库 默认情况下 fancyBox 3 对不同类型的内容使用不同的过渡 a href img jpg img sr
  • Android 意图数据库

    是否有一个意图数据库可以搜索发布公共服务的应用程序 例如 我可能有一个关于可以应用于照片应用程序中的照片的过滤器的想法 但是我应该出于什么目的发布我的过滤器以便其他应用程序可以找到它并使用它 所以问题是是否有一个或多或少标准的意图数据库以及
  • 如何在容器化世界中独特地解决“流程”?

    这是一个普遍问题 但出于争论的目的 您可以假设我们有一组通过 AMQP 和 HTTP 组合进行通信的进程 有两种具体情况需要考虑 最简单的一个 Q 如果 A 向 B 发送消息 B 如何识别 A 发送回复的位置 A A 必须以某种方式告诉 B
  • 如何在悬停时更改父
  • 的样式
  • 我有一个 WordPress 网站 在我的本地主机上 它使用 ul 用于自定义菜单 我怎样才能改变CSS li 悬停时only如果它有一个 ul 子菜单 所有主菜单项都有一个边框半径 我想在当前项目 下面的服务 上删除它 例如 div cl
  • 我可以使用 Jython 运行 numpy 和 pandas

    我们有一些 Java 代码想要与计划用 Python 编写的新代码一起使用 因此我们对使用 Jython 感兴趣 然而 我们还想使用 numpy 和 pandas 库在此 Python 代码中进行复杂的统计分析 是否可以从 Jython 调
  • 提高 Android 位图上 getpixel() 和 setpixel() 的速度

    All 当我注意到有多慢之后getPixel and setPixel是 不确定是哪一个 猜想两者都不是涡轮增压的 我快速编码了一个容器Bitmap使用int 数组来处理位图操作 已经 它明显更快 但这还不够 请问您能建议如何进一步加快速度
  • 使用 Scala 中的可变参数

    我正在抓狂地试图弄清楚如何执行以下操作 def foo msf String o Any os Any println String format msf o List os 我必须用一个来声明该方法是有原因的o and an os Seq
  • 如何在 RXJS 中启动和停止可观察的间隔?

    我有一个非常简单的 timeInterval 可观察对象 我想在不断开订阅者连接的情况下启动 停止传输 无论可观察状态如何 都应该坐下来等待 有可能吗 如果可以的话怎么办 var source Rx Observable interval
  • 在 MS-Access 中插入带有日期时间的 SQL 命令

    我正在 MS Access 2007 中尝试以下查询 但在时间字段上失败 INSERT INTO LOG EMPLOYEECODE STATUSID LOCATIONID TIME DURATION SHIFTID LATECOMING E
  • 创建索引需要很长时间

    我在 MongoDB 中创建了一个集合 其中包含11446615文件 每个文档具有以下形式 id ObjectId 4e03dec7c3c365f574820835 httpReferer http www somewebsite pl a
  • wamp 本地主机上的 Amazon S3 SSL 错误

    我尝试在本地主机上使用 PHP Amazon S3 进行测试 但不断收到相同的错误 致命错误 未捕获异常 cURL Exception 消息为 cURL 资源 资源 ID 69 cURL 错误 SSL 证书问题 请验证 CA 证书没问题 详
  • java 的 System.getProperty("user.dir") 在 .NET 中的等价物是什么?

    我试图获取单元测试中文件的完整路径 该文件位于项目的文件夹中 我尝试使用 Directory GetCurrentDirectory 但这会返回我的测试正在运行的目录 我想要项目 或解决方案 的目录 而不必在其中进行硬编码 然后我可以附加文
  • angular2:如何将对象复制到另一个对象中

    请帮助我使用 Angular 2 将对象复制到另一个对象中 在 Angular 中 我使用 angular copy 将对象复制到旧对象的松散引用 但是 当我在 Angular 2 中使用相同的方法时 出现以下错误 错误 角度未定义 Sol
  • React Router v4 - 如何防止重定向循环?

    我想要实现的目标是拥有我的App如果状态的 uid 为 null 则组件重定向到 login 路由 重定向工作正常 如果 uid 为空 它将始终将您重定向到 login 但问题是一旦您进入 login 路线 它就不会停止重定向 抛出的错误是
  • 我应该使用什么标准来评估 Perl“应用程序服务器”(mod_perl 替代品)?

    简洁版本 我应该使用什么标准来评估 Perl 应用程序服务器 mod perl 替代品 的可能候选者 我们正在寻找某种框架 它允许重复执行各种 Perl 程序 作为服务 而不会产生以下成本 每次执行时重新启动 perl 解释器一次 每次执行
  • 如何在python 3中按本地语言对拉丁语进行排序?

    在很多情况下 用户的语言不是 latin 脚本 示例包括 希腊语 俄语 中文 在大多数情况下 排序是通过 首先对特殊字符和数字进行排序 虽然是当地语言的数字 其次是当地语言文字中的单词 最后是一般 utf 排序规则中的任何非本地字符 例如法
  • 如何在 python-igraph 中种子图生成器?

    有没有什么方法可以为使用 python igraph 生成的以下 Watts Strogatz 图提供种子 以便每次运行脚本时我都能得到相同的 SW 图实现 import igraph graph igraph Graph Watts St
  • 学习 VHDL 的最佳方法? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 从列表中选择随机单词?

    我无法从另一个文件的列表中随机选择单词 事实上我什至无法让它选择任何单词 我不确定如何连接这两个文件 希望有人能帮忙 我是初学者 所以请尽可能简单地解释一下 我有 2 个文件 一个名为 program cs 另一个名为 WordList c
  • 在版本 4 中将节点动态添加到 D3 Force Layout

    我正在尝试实现一个简单的力布局 其中可以动态添加和删除节点 没有链接 我成功地在 D3 版本 3 中实现了这个概念 但我无法将其转换为版本 4 添加和更新节点后 模拟冻结 传入的圆圈绘制在 svg 的左上角 有人知道为什么会这样吗 谢谢你的