多个力布局图,其中 d3 位于单独的 svg/div 中

2024-03-28

我在使用 d3 创建多个力布局图并从 json 文件读取数据时遇到问题。我使用 for 循环来迭代图表,为每个图表创建一个单独的 div,其中包含一个 svg。问题是,力布局仅应用于最后创建的布局,因此基本上其他布局仅在左上角显示一个点。我可以通过在每次迭代结束时放置一个 for 循环来部分解决这个问题,但我仍然失去了单独图形的交互能力。

找到下面的代码,提前致谢。

干杯,迈克尔

var color = d3.scale.category20();

var force = new Array();
var div = new Array();
var svg = new Array();
var graph = new Array();
var link;
var node;
var width = 360;
var height = 360;
var brush = new Array();
var shiftKey;
var count = 0;

//loop through the different subsystems in the json-file
for(name_subsystem in graphs) {
    //add a div for each subsystem
    div[count] = document.createElement("div");
    div[count].style.width = "360px";
    div[count].style.height = "360px";
    div[count].style.cssFloat="left";
    div[count].id = name_subsystem;

    document.body.appendChild(div[count]);


    //force is called. all attributes with default values are noted. see API reference on github.
    force[count] = d3.layout.force()
        .size([width, height])
        .linkDistance(20)
        .linkStrength(1)
        .friction(0.9)
        .charge(-30)
        .theta(0.8)
        .gravity(0.1);

    div[count].appendChild(document.createTextNode(name_subsystem));

    //create the svg rectangle in which other elements can be visualised
    svg[count] = d3.select("#"+name_subsystem)
        .on("keydown.brush", keydown)
        .on("keyup.brush", keyup)
      .append("svg")
        .attr("width", width)
        .attr("height", height)
        .attr("id",name_subsystem);

    brush[count] = svg[count].append("g")
        .datum(function() { return {selected: false, previouslySelected: false}; })
        .attr("class", "brush");

    //force is started
    force[count]
        .nodes(graphs[name_subsystem].nodes)
        .links(graphs[name_subsystem].links)
        .start();

    //link elements are called, joined with the data, and links are created for each link object in links
    link = svg[count].selectAll(".link")
        .data(graphs[name_subsystem].links)
        .enter().append("line")
        .attr("class", "link")
        .style("stroke-width", function(d) { return Math.sqrt(d.thickness); })
        .style("stroke", function(d){
            if (d.linktype === 'reactant'){
                return "black";
            } else {
                return "red";
            }
        });

    //node elements are called, joined with the data, and circles are created for each node object in nodes
    node = svg[count].selectAll(".node")
        .data(graphs[name_subsystem].nodes)
        .enter().append("circle")
        .attr("class", "node")
        //radius
        .attr("r", 5)
        //fill
        .attr("fill", function(d) {
            if (d.type === 'metabolite') {
                return "blue";
            } else {
                return "red";
            }
        })
        .on("mousedown", function(d) {
            if (!d.selected) { // Don't deselect on shift-drag.
                if (!shiftKey) node.classed("selected", function(p) { return p.selected = d === p; });
            else d3.select(this).classed("selected", d.selected = true);
            }
        })
        .on("mouseup", function(d) {
            if (d.selected && shiftKey) d3.select(this).classed("selected", d.selected = false);
        })
        .call(force[count].drag()
            .on("dragstart",function dragstart(d){
                d.fixed=true;
                d3.select(this).classed("fixed",true);
            })
        );


    //gives titles to nodes. i do not know why this is separated from the first node calling.
    node.append("title")
        .text(function(d) { return d.name; });

    //enable brushing of the network
    brush[count].call(d3.svg.brush()
        .x(d3.scale.identity().domain([0, width]))
        .y(d3.scale.identity().domain([0, height]))
        .on("brushstart", function(d) {
            node.each(function(d) { d.previouslySelected = shiftKey && d.selected; });
        })
        .on("brush", function() {
            var extent = d3.event.target.extent();
            node.classed("selected", function(d) {
                return d.selected = d.previouslySelected ^
                (extent[0][0] <= d.x && d.x < extent[1][0]
                && extent[0][1] <= d.y && d.y < extent[1][1]);
            });
        })
        .on("brushend", function() {
            d3.event.target.clear();
            d3.select(this).call(d3.event.target);
        })
    );

    //applies force per step or 'tick'. 
    force[count].on("tick", function() {
        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; });

        node.attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; });
    });
    //with this it works partly
    //for (var i = 0; i < 5000; ++i)force[count].tick();
    count++;
};

function keydown() {
  if (!d3.event.metaKey) switch (d3.event.keyCode) {
    case 38: nudge( 0, -1); break; // UP
    case 40: nudge( 0, +1); break; // DOWN
    case 37: nudge(-1,  0); break; // LEFT
    case 39: nudge(+1,  0); break; // RIGHT
  }
  shiftKey = d3.event.shiftKey || d3.event.metaKey;
}

function keyup() {
  shiftKey = d3.event.shiftKey || d3.event.metaKey;
}

编辑:评论后更新了代码,仍然是同样的问题。


我只研究力布局,同时处理许多图表。

1 您不需要为每个图表都有一个计数变量。

2 不要将这些变量(force、svg、graph)作为数组。没有必要。只需在上面将它们声明为 (var svg;) 即可。当您调用该函数时,它会自动创建不同的副本,并且 DOM 单独维护它们。因此,您在图中使用的每个变量都应在函数顶部声明。

3 您正在同时绘制所有图形,因此当调用新图形时,前一个图形将停止在 svg 上制作,这就是为什么只有最后一个图形构建成功的原因。因此,请在较小的时间间隔后绘制它们。

<html>
<script>
function draw_graphs(graphs){

var color = d3.scale.category20();

var force;
var div;
var svg;
var graph;
var link;
var node;
var width = 360;
var height = 360;
var brush = new Array();
var shiftKey;


//loop through the different subsystems in the json-file
for(name_subsystem in graphs) {
//add a div for each subsystem
div = document.createElement("div");
div.style.width = "360px";
div.style.height = "360px";
div.style.cssFloat="left";
div.id = name_subsystem;

document.body.appendChild(div); 


//force is called. all attributes with default values are noted. see API reference on github.
force = d3.layout.force()
    .size([width, height])
    .linkDistance(20)
    .linkStrength(1)
    .friction(0.9)
    .charge(-30)
    .theta(0.8)
    .gravity(0.1);

div.appendChild(document.createTextNode(name_subsystem));

//create the svg rectangle in which other elements can be visualised
svg = d3.select("#"+name_subsystem)
    .on("keydown.brush", keydown)
    .on("keyup.brush", keyup)
  .append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("id",name_subsystem); 

brush = svg.append("g")
    .datum(function() { return {selected: false, previouslySelected: false}; })
    .attr("class", "brush"); 

//force is started
force
    .nodes(graphs[name_subsystem].nodes)
    .links(graphs[name_subsystem].links)
    .start();

//link elements are called, joined with the data, and links are created for each link object in links
link = svg.selectAll(".link")
    .data(graphs[name_subsystem].links)
    .enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function(d) { return Math.sqrt(d.thickness); })
    .style("stroke", function(d){
        if (d.linktype === 'reactant'){
            return "black";
        } else {
            return "red";
        }
    });

//node elements are called, joined with the data, and circles are created for each node object in nodes
node = svg.selectAll(".node")
    .data(graphs[name_subsystem].nodes)
    .enter().append("circle")
    .attr("class", "node")
    //radius
    .attr("r", 5)
    //fill
    .attr("fill", function(d) {
        if (d.type === 'metabolite') {
            return "blue";
        } else {
            return "red";
        }
    })
    .on("mousedown", function(d) {
        if (!d.selected) { // Don't deselect on shift-drag.
            if (!shiftKey) node.classed("selected", function(p) { return p.selected = d === p; });
        else d3.select(this).classed("selected", d.selected = true);
        }
    })
    .on("mouseup", function(d) {
        if (d.selected && shiftKey) d3.select(this).classed("selected", d.selected = false);
    })
    .call(force.drag()
        .on("dragstart",function dragstart(d){
            d.fixed=true;
            d3.select(this).classed("fixed",true);
        })
    );


//gives titles to nodes. i do not know why this is separated from the first node calling.
node.append("title")
    .text(function(d) { return d.name; });

//enable brushing of the network
brush.call(d3.svg.brush()
    .x(d3.scale.identity().domain([0, width]))
    .y(d3.scale.identity().domain([0, height]))
    .on("brushstart", function(d) {
        node.each(function(d) { d.previouslySelected = shiftKey && d.selected; });
    })
    .on("brush", function() {
        var extent = d3.event.target.extent();
        node.classed("selected", function(d) {
            return d.selected = d.previouslySelected ^
            (extent[0][0] <= d.x && d.x < extent[1][0]
            && extent[0][1] <= d.y && d.y < extent[1][1]);
        });
    })
    .on("brushend", function() {
        d3.event.target.clear();
        d3.select(this).call(d3.event.target);
    })
);

//applies force per step or 'tick'. 
force.on("tick", function() {
    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; });

    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
});
//with this it works partly
//for (var i = 0; i < 5000; ++i)force[count].tick();
};

function keydown() {
if (!d3.event.metaKey) switch (d3.event.keyCode) {
case 38: nudge( 0, -1); break; // UP
case 40: nudge( 0, +1); break; // DOWN
case 37: nudge(-1,  0); break; // LEFT
case 39: nudge(+1,  0); break; // RIGHT
}
shiftKey = d3.event.shiftKey || d3.event.metaKey;
}

function keyup() {
shiftKey = d3.event.shiftKey || d3.event.metaKey;
}

}
</script>


<script>
$(document).ready(function() {
draw_graphs("pass here the json file");


// this will drawn 2nd graph after 1 second.              
var t = setTimeout(function(){
draw_graphs("pass here json file");
}, 1000)

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

多个力布局图,其中 d3 位于单独的 svg/div 中 的相关文章

  • Durandal SPA 与打字稿有关的问题

    我使用 TypeScript 1 8 将我的 durandal SPA 应用程序从 VS 2012 更新到 VS 2015 它将生成 JavaScript ECMA5 我解决了所有构建错误 但我无法修复一个名为 return 语句只能在函数
  • 需要一个正则表达式将 css 类添加到第一个和最后一个列表项

    更新 谢谢大家的意见 一些附加信息 它实际上只是我正在使用的一小部分标记 20 行 目的是利用正则表达式来完成工作 我还能够修改脚本 电子商务脚本 以在构建导航时插入类 我想限制我所采用的黑客数量 以便在更新到软件的最新版本时让事情变得更容
  • 从本地 html/javascript 网站插入 mySQL 数据库

    我正在尝试做什么 我的程序的目的是插入数据local HTML JS网站变成online 非本地 mySQL数据库 到目前为止我尝试过的 我试图用来实现此目的的原始方法是让我的本地网站使用 javascript 通过在线发布数据PHP文件
  • React Native 中 fontAwesome 图标的圆形轮廓

    我想使用 fontAwesome 图标 使其位于圆圈的中间 我想将它用作一个图标项 我读到我们可以将它与圆形图标一起使用并将其放置在其中 但我无法使其工作 import IconFA from react native vector ico
  • Nodejs 异步 Promise 队列

    我需要使用速率受限的 API 例如 我一秒钟只能进行 10 个 API 调用 因此我需要等待当前秒结束才能进行另一个 API 调用 为了实现这一目标 我想创建一个可以自行管理的异步队列 它的主要功能是让我向队列添加一个新的 Promise
  • 复合组件和 CSS

    I have newcss css formdiv width 30 margin 150 auto 和复合组件
  • 使用mysql数据按高低价格排序

    这是我所拥有的以及我想做的 我的 MySql 数据库中有 12 个项目 4 个产品为 4 99 4 个产品为 3 99 4 个产品为 2 99 我意识到我可以像这样查询数据库 它会给我一个该价格的产品列表
  • Lodash _.hasIntersection?

    我想知道两个或多个数组是否有共同的项目 但我不在乎这些项目是什么 我知道 lodash 有一个 intersection方法 但我不需要它来遍历每个数组的每个项目 相反 我需要类似的东西 hasIntersection一旦找到第一个常见的出
  • 使标签充当输入按钮

    我怎样才能做一个 a href http test com tag test Test a 就像表单按钮一样 通过充当表单按钮 我的意思是 当单击链接执行操作时method get 或 post 以便能够通过 get 或 post 捕获它
  • 无需画布/显示器即可拍摄隐形 WebRTC/视频照片

    我读了拍摄静态照片 https developer mozilla org en US docs Web API WebRTC API Taking still photos来自 MDN 的描述如何从网络摄像头捕获照片 使用视频元素和med
  • 检查是否安装了 Google Analytics 或 Universal Analytics?

    我正在尝试通过 JavaScript 来确定是否加载了 Google Analytics 或 Universal Analytics 一些客户仍在使用旧的 Google Analytics 我们希望推出一个收集数据的 JavaScript
  • Xpath 获取 if href 包含字符串的一部分

    您好 我尝试获取包含 href p random tagged see 的所有元素 这是我的路线 div preceding h2 text Most recent div div a href p tagged see 我该如何修复此代码
  • 使用外部按钮选择下一个/上一个单选按钮

    我正在制作一种幻灯片形式 当用户单击下一张图像时 还必须选择单选按钮 我的滑动功能可以正常工作 下一个按钮 也可以工作 但我有点坚持使用 上一个 按钮 不明白为什么它不起作用 fiddle http jsfiddle net V4tdx 这
  • 分配函数后如何删除 onmouseout 事件?

    我有一个问题 我正在为 onmouseout 事件分配一个函数 但运行该事件后 我需要将其删除 将非常感谢您的帮助 这取决于你的代码 如果你用 d3 这样做 那么你可以说 在 onmouseout 事件函数中 element on mous
  • 如何从 Visual Studio Code API 打开浏览器

    我只是在探索一种从用于开发扩展的 Visual Studio Code API 打开默认浏览器的方法 以下是我的代码 var disposable vscode commands registerCommand extension brow
  • 使用 NodeJS 创建 YouTube 播放列表

    我正在尝试使用 NodeJS 服务器创建 YouTube 播放列表 我已按照 Oauth 的 NodeJS 快速入门说明进行操作 如以下链接所示 https github com youtube api samples blob maste
  • 如何将 Django 数据库中的模板标签解释/渲染为 HTML

    我正在尝试添加带有来自 Django 管理站点的图像的帖子 但安全 自动转义关闭过滤器无法解释 Django 的模板标签 My input and page look like 复制图像地址 给出http 127 0 0 1 8000 7B
  • 如何在控制台中隐藏日志消息的来源?

    当将消息输出到控制台时 还会显示源代码 在 Chrome 开发者工具中 它位于右侧 console log Foo Source Foo test js 1 Output 但是 在某些网站上 会显示消息without正在显示的源 例如Fac
  • 如何在 JavaScript 中将日期时间微格式转换为本地时间?

    我有一个页面当前正在使用日期时间微格式 http microformats org wiki datetime design pattern显示时间戳 但我只显示我自己的时区的人类可读时间
  • 如何将函数导入到Vue组件中?

    我正在尝试将单个函数导入到我的 Vue 组件中 我为我的函数创建了一个单独的 js 文件 randomId js exports randomId gt My function 在我的 Vue 组件中 我导入了 Random js let

随机推荐

  • 通过 R 中的因子向量化 cumsum

    我正在尝试在一个非常大的数据帧 约 220 万行 中创建一个列 用于计算每个因子级别的 1 的累积和 并在达到新的因子级别时重置 下面是一些与我自己的类似的基本数据 itemcode lt c a1 a1 a1 a1 a1 a2 a2 a3
  • 查找 boost multi index 标签到索引和索引数量

    我有一个模板类 CrMultiIndex 它接收 boost 多索引 GlobalHash 的定义作为模板参数 I need 根据使用的索引向我的模板类添加统计信息 所以我需要一种方法在初始化时使用现有索引的数量调整向量 m StatsBy
  • iOS10 SDK什么时候设置视图帧大小?

    多年来 我一直在 Swift 和 ObjC 中使用这种技术来制作圆形视图 view layer cornerRadius view frame size width 2 view clipsToBounds true 当 Storyboar
  • 串行版本 UID 有何用途? [复制]

    这个问题在这里已经有答案了 我正在创建一个 Java 应用程序 当创建一个与 ADT 一起使用的接口时 它发现需要将一个随机数初始化为 ID 号 public class StackFullException extends Runtime
  • DomIcon 的集群

    我正在尝试制作集群H map DomMarker 正在使用H map DomIcon与 HTML 代码 但原生的 Here Map 聚类不起作用 仅当我使用简单的H map Icon 但由于这被渲染为canvas图层 我无法使用自己的标记
  • MFC:如何捕获Web浏览器控件中的链接单击事件?

    我有一个带有 Web 控件的 MFC 应用程序 单击可单击链接时 它将使用 IE 打开 而不是默认浏览器 问题 有没有办法强制使用默认浏览器打开它 如果没有 我如何捕获链接单击事件 以便稍后可以操纵单击事件 谢谢 不 据我所知还没有 查看有
  • 在 Mathematica 中导入 Google Sketchup 模型

    Google 的 Sketchup 是一个漂亮 简单的 3D 对象建模器 此外 谷歌还拥有巨大的3D 对象仓库 http sketchup google com 3dwarehouse 因此 如果您在这方面不是特别有天赋 实际上您不必自己做
  • R 包“partykit”在 ctree_control 中未使用参数

    我想使用 partykit 包通过 ctree 和 cforest 构建分类树和森林 由于我的数据集包含 50000 行和 30 列 因此我想将 minsplit 设置为 150 将 minbucket 设置为 50 不幸的是 当我输入我的
  • 与 xgboost 并行线程?

    根据其文档 xgboost 有一个 n jobs 参数 但是 当我尝试设置 n jobs 时 出现此错误 TypeError init got an unexpected keyword argument n jobs 其他一些参数 如 r
  • OpenSSL 错误 - 无法获取本地颁发者证书

    我有一个简单的链设置 在这种情况下可以成功验证 openssl version OpenSSL 1 0 2m 2 Nov 2017 openssl verify CAfile chain pem cert pem cert pem OK 但
  • ember 数据验证的标准模式是什么? (无效状态,变成无效……)

    我已经为此苦苦挣扎了一段时间 让我们看看是否有人可以帮助我 尽管自述文件中没有明确说明 但 ember data 提供了一定程度的验证支持 您可以在代码和文档的某些部分看到 https github com emberjs data blo
  • 查找堆中元素的位置

    考虑以下元素列表 h 38 203 1 45 39 10 34 90 10 2 100 1 如果将其放入基于数组的堆中 它将按以下方式查找 import heapq heapq heapify h now we have a heap th
  • 如何使用 Javascript 在离开页面之前调用函数

    我想在离开页面之前执行一个函数 而不显示确认弹出窗口JavaScript仅有的 我已尝试使用下面的代码 但它不起作用或与onbeforeunload但它总是显示弹出窗口 var result test if window onbeforeu
  • 混合 C++11 std::thread 和 C 系统线程(即 pthreads)

    我正在编写一个多线程 C 程序 并希望使用多线程 C 库 该库希望我使用本机系统方法为其创建一些工作线程 并使用如下代码将控制权传递给其 run 函数 void system specific thread init ifdef WIN32
  • cpprestsdk:架构 x86_64 的未定义符号

    我已经访问了所有其他问题 但据我所知 没有一个问题是我的问题 在 MacBook Pro 16GB 内存 Intel Core I7 上运行 OS X El Capitan 10 11 6 我也运行过brew doctor 但没有发现任何会
  • ui-bootstrap 分页在初始化时重置当前页面

    我正在使用 ui bootstrap angular bootstrap 库中的分页指令 我在初始化时遇到问题 当我通过 url 导航到特定页面时 会出现问题 发生的情况是 我的控制器使用 stateParams 中的正确页面进行初始化 然
  • 如何在跨度内的 CSS 中创建所有浏览器兼容的悬挂缩进样式

    我唯一发现的是 hang text indent 3em margin left 3em 实现此目的的唯一方法是将文本放入段落中 这会导致那些非常难看的额外行 我宁愿把它们放在一个 span class hang span 类型的事物 我还
  • 使用 Karma / Jasmine 进行 Angular 8 测试 -> 角度路由中的 loadChildren 未覆盖 100% 代码覆盖率

    从 Angular 7 升级到 Angular 8 后 应用程序路由的 loadChildren 发生了重大变化 当这些问题得到修复并且所有测试都在运行时 我不再获得 100 的代码覆盖率 因为 loadChildren 不再是 字符串 而
  • 直接调用 vs 调用 vs 启动

    我在使用 Tivoli Workload Scheduler 运行批处理文件时遇到此问题 有一个第三方程序 假设它的名称是program exe 该批处理文件包含以下命令来调用program exe program exe param1 p
  • 多个力布局图,其中 d3 位于单独的 svg/div 中

    我在使用 d3 创建多个力布局图并从 json 文件读取数据时遇到问题 我使用 for 循环来迭代图表 为每个图表创建一个单独的 div 其中包含一个 svg 问题是 力布局仅应用于最后创建的布局 因此基本上其他布局仅在左上角显示一个点 我