jjzjj

javascript - vis.js - 在屏幕上适合一组节点

coder 2024-07-23 原文

我在 vis.js 中有一个包含许多节点的网络图。选择某个组时,我想平移和缩放图形,以便该组的所有节点都适合屏幕。

我正在遍历图中的每个节点并计算我感兴趣的所有节点的边界框,然后我使用 moveTo 方法将图移动并缩放到该边界的中心盒子。伪代码:

var allNodes = data.nodes.get({
    returnType: "Object"
});
var bounds;
for (n in allNodes) {
    if (matchesCondition(allNodes[n])) {
        bounds = extendBounds(bounds, graph.getBoundingBox(allNodes[n]));                   
    }
}
var newViewport = {
    position: {
        x: (bounds.x1+bounds.x2)/2;
        y: (bounds.y1+bounds.y2)/2;
    },
    // What is the visible width, where do I get it from?
    scale: Math.min(??? / (bounds.x2-bounds.x1), ??? / (bounds.y2-bounds.y1))
}
graph.moveTo(newViewport);

问题:如何计算比例,即用什么替换 ???在上面的伪代码中?

最佳答案

样本数据来自 Vis.js groups example .

要适合视口(viewport),您可以简单地使用 native .fit() 方法。自 the documentation不提供标签化链接,这里是 API 描述:

Zooms out so all nodes fit on the canvas. You can supply options to customize this:

{
  nodes:[Array of nodeIds],
  animation: { //can be a boolean too
    duration: Number
    easingFunction: String
  }
}

The nodes can be used to zoom to fit only specific nodes in the view.

考虑到这一点,我们需要做的就是获取给定组中的所有节点。令人惊讶的是,用户空间 API 似乎没有为此提供方法(?),因此需要一个小的过滤方法。

//TODO: Is there no user-land API for this?
var getGroup = function getGroup(nodeId) {
  var nodesHandler = network.nodesHandler;
  var innerNodes = nodesHandler.body.nodes;
  //Lazily assume ids match indices
  var node = innerNodes[nodeId];
  return node.options.group;
};

var getGroupNodes = function getGroupNodes(group) {
  // http://elijahmanor.com/reducing-filter-and-map-down-to-reduce/
  var filtered = nodes.reduce(function(output, node) {
    if (node.group === group) {
      output.push(node.id);
    }
    return output;
  }, []);
  return filtered;
};

//START Vis.js group example

var color = 'gray';
var len = undefined;

var nodes = [{
  id: 0,
  label: "0",
  group: 0
}, {
  id: 1,
  label: "1",
  group: 0
}, {
  id: 2,
  label: "2",
  group: 0
}, {
  id: 3,
  label: "3",
  group: 1
}, {
  id: 4,
  label: "4",
  group: 1
}, {
  id: 5,
  label: "5",
  group: 1
}, {
  id: 6,
  label: "6",
  group: 2
}, {
  id: 7,
  label: "7",
  group: 2
}, {
  id: 8,
  label: "8",
  group: 2
}, {
  id: 9,
  label: "9",
  group: 3
}, {
  id: 10,
  label: "10",
  group: 3
}, {
  id: 11,
  label: "11",
  group: 3
}, {
  id: 12,
  label: "12",
  group: 4
}, {
  id: 13,
  label: "13",
  group: 4
}, {
  id: 14,
  label: "14",
  group: 4
}, {
  id: 15,
  label: "15",
  group: 5
}, {
  id: 16,
  label: "16",
  group: 5
}, {
  id: 17,
  label: "17",
  group: 5
}, {
  id: 18,
  label: "18",
  group: 6
}, {
  id: 19,
  label: "19",
  group: 6
}, {
  id: 20,
  label: "20",
  group: 6
}, {
  id: 21,
  label: "21",
  group: 7
}, {
  id: 22,
  label: "22",
  group: 7
}, {
  id: 23,
  label: "23",
  group: 7
}, {
  id: 24,
  label: "24",
  group: 8
}, {
  id: 25,
  label: "25",
  group: 8
}, {
  id: 26,
  label: "26",
  group: 8
}, {
  id: 27,
  label: "27",
  group: 9
}, {
  id: 28,
  label: "28",
  group: 9
}, {
  id: 29,
  label: "29",
  group: 9
}];
var edges = [{
  from: 1,
  to: 0
}, {
  from: 2,
  to: 0
}, {
  from: 4,
  to: 3
}, {
  from: 5,
  to: 4
}, {
  from: 4,
  to: 0
}, {
  from: 7,
  to: 6
}, {
  from: 8,
  to: 7
}, {
  from: 7,
  to: 0
}, {
  from: 10,
  to: 9
}, {
  from: 11,
  to: 10
}, {
  from: 10,
  to: 4
}, {
  from: 13,
  to: 12
}, {
  from: 14,
  to: 13
}, {
  from: 13,
  to: 0
}, {
  from: 16,
  to: 15
}, {
  from: 17,
  to: 15
}, {
  from: 15,
  to: 10
}, {
  from: 19,
  to: 18
}, {
  from: 20,
  to: 19
}, {
  from: 19,
  to: 4
}, {
  from: 22,
  to: 21
}, {
  from: 23,
  to: 22
}, {
  from: 22,
  to: 13
}, {
  from: 25,
  to: 24
}, {
  from: 26,
  to: 25
}, {
  from: 25,
  to: 7
}, {
  from: 28,
  to: 27
}, {
  from: 29,
  to: 28
}, {
  from: 28,
  to: 0
}];

// create a network
var container = document.getElementById('mynetwork');
var data = {
  nodes: nodes,
  edges: edges
};
var options = {
  nodes: {
    shape: 'dot',
    size: 30,
    font: {
      size: 32,
      color: '#ffffff'
    },
    borderWidth: 2
  },
  edges: {
    width: 2
  }
};
network = new vis.Network(container, data, options);

//END Vis.js group example

network.on("click", function(e) {
  //Zoom only on single node clicks, zoom out otherwise
  if (e.nodes.length !== 1) {
    network.fit();
    return;
  }
  var nodeId = e.nodes[0];
  //Find out what group the node belongs to
  var group = getGroup(nodeId);
  //TODO: How do you want to handle ungrouped nodes?
  if (group === undefined) return;
  var groupNodes = getGroupNodes(group);
  network.fit({
    nodes: groupNodes
  });
});
html,
body,
#mynetwork {
  width: 100%;
  height: 100%;
  margin: 0;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/vis/4.3.0/vis.min.js"></script>
<div id="mynetwork"></div>

关于javascript - vis.js - 在屏幕上适合一组节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31159422/

有关javascript - vis.js - 在屏幕上适合一组节点的更多相关文章

  1. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

  2. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  3. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  4. ruby-on-rails - Assets 管道损坏 : Not compiling on the fly css and js files - 2

    我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1

  5. ruby-on-rails - Rails - 理解 application.js 和 application.css - 2

    rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:

  6. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  7. node.js - 如何在 Travis CI 上的一个项目中运行 Node.js 和 Ruby 测试 - 2

    我有一个包含多个组件的存储库,其中大部分是用JavaScript(Node.js)编写的,一个是用Ruby(RubyonRails)编写的。我想要一个.travis.yml文件来触发一个运行每个组件的所有测试的构建。根据thisTravisCIGoogleGroupthread,目前还没有官方支持。我的目录结构是这样的:.├──构建服务器├──核心├──扩展├──网络应用├──流浪文件├──package.json├──.travis.yml└──生成文件我希望能够运行特定版本的Ruby(2.2.2)和Node.js(0.12.2)。我已经有了一个make目标,所以maketest在每

  8. 区块链入门教程(6)--WeBASE-Front节点前置服务安装 - 2

    文章目录1.任务背景2.任务目标3.相关知识点4.任务实操4.1安装配置JDK4.2启动FISCOBCOS4.3下载解压WeBASE-Front4.4拷贝sdk证书文件4.5启动节点4.6访问节点4.7检查运行状态5.任务总结1.任务背景FISCOBCOS其实是有控制台管理工具,用来对区块链系统进行各种管理操作。但是对于初学者来说,还是可视化界面更友好,本节就来介绍WeBASE管理平台,这是一款微众银行开源的自研区块链中间件平台,可以降低区块链使用的门槛,大幅提高区块链应用的开发效率。微众银行是腾讯牵头设立的民营银行,在国内民营银行里还是比较出名的。微众银行参与FISCOBCOS生态建设,一定

  9. ruby - 选择包含子节点内文本的父节点 - 2

    基本上我想选择一个节点(div),其中它的子节点(h1,b,h3)包含指定的文本。Childtext1Childtext2...Childtext3我期待的是/html/div/而不是/html/div/h1我在下面有这个,但不幸的是返回了child,而不是div的xpath。expression="//div[contains(text(),'Childtext1')]"doc.xpath(expression)我期待的是/html/div/而不是/html/div/h1那么有没有一种方法可以简单地使用xpath语法来做到这一点? 最佳答案

  10. python - 这些脚本语言中哪种更适合渗透测试? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭9年前。Improvethisquestion首先,我想避免一场关于语言的口水战。可供选择的语言有Perl、Python和Ruby。我想提一下,我对所有这些都很满意,但问题是我不能只专注于一个。例如,如果我看到一个很棒的Perl模块,我必须尝试一下。如果我看到一个不错的Python应用程序,我必须知道它是如何制作的。如果我看到RubyDSL或一些Ruby巫术,我就会迷上Ruby一段时间。目前我是一名Java开发人员,但计划在不久的将来

随机推荐