分层边缘集群组名

我有以下聚类图,它大部分工作正常。我猜这与我如何将东西打包在一起有关?

function packageImports(nodes) {

  var map = {},

    imports = [];


  // Compute a map from name to node.

  nodes.forEach(function(d) {

    map[d.data.name] = d;

  });


  // For each import, construct a link from the source to target node.

  nodes.forEach(function(d) {

    if (d.data.imports) d.data.imports.forEach(function(i) {

      imports.push(map[d.data.name].path(map[i]));

    });

  });


  return imports;

}

.node {

  font: 300 11px "Helvetica Neue", Helvetica, Arial, sans-serif;

  fill: #444;

}


.node:hover {

  fill: #000;

}


.link {

  stroke: steelblue;

  stroke-opacity: 0.5;

  fill: none;

  pointer-events: none;

  stroke-width: 1px;

  stroke-linecap: round;

}


.node:hover,

.node--source,

.node--target {

  font-weight: 700;

}



/* text color */


.node--source {

  fill: red;

}



/* text color */


.node--target {

  fill: red;

}


.link--source,

.link--target {

  stroke-opacity: 1;

  stroke-width: 2px;

}



/* line color */


.link--source {

  stroke: red;

}



/* line color */


.link--target {

  stroke: red;

}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>


我所追求的是两件事

  1. 我需要每个组都显示一个标题。EG 数据库说它们是数据库

  2. 3 条颜色线(我目前有 2 条颜色相同),1 条用于依赖,1 条用于依赖,1 条用于两者

D3 的新手不确定如何实现这些?


互换的青春
浏览 108回答 1
1回答

当年话下

我认为您遇到的问题是度数和弧度之间的转换。这就是为什么你必须在例程中使用聪明的解决方案rotate - translate - rotate。我已将集群更改为以弧度输出,然后groups作为文本添加为节点的父节点。我还更改了链接类,使传入和传出链接的颜色不同。如果一个链接有两个类,那么它是绿色的。你把类link--source和link--target类颠倒了,我把它颠倒了。var diameter = 900,&nbsp; radius = diameter / 2,&nbsp; innerRadius = radius - 180;var cluster = d3.cluster()&nbsp; .size([2 * Math.PI, innerRadius]);var line = d3.radialLine()&nbsp; .curve(d3.curveBundle.beta(0.2))&nbsp; .radius(function(d) {&nbsp; &nbsp; return d.y;&nbsp; })&nbsp; .angle(function(d) {&nbsp; &nbsp; return d.x;&nbsp; });var svg = d3.select("body").append("svg")&nbsp; .attr("width", diameter)&nbsp; .attr("height", diameter)&nbsp; .append("g")&nbsp; .attr("transform", "translate(" + radius + "," + radius + ")");var link = svg.append("g").selectAll(".link"),&nbsp; node = svg.append("g").selectAll(".node"),&nbsp; group = svg.append("g").selectAll(".group");let samlDeps = [&nbsp; 'dsi.backend.SAML-ASSERTIONS',&nbsp; 'dsi.frontend.OIDC'];var arc = d3.arc()&nbsp; .innerRadius(10)&nbsp; .outerRadius(15);var classes = [{&nbsp; &nbsp; 'name': 'dsi.frontend.HELP',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.frontend.PROFILE',&nbsp; &nbsp; &nbsp; 'dsi.frontend.INTERACTIONS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SERVICES',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SUPPORT',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.CDN',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.frontend.INTERACTIONS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.frontend.PROFILE',&nbsp; &nbsp; &nbsp; 'dsi.frontend.HELP',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SERVICES',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SUPPORT',&nbsp; &nbsp; &nbsp; 'dsi.db.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.frontend.OIDC',&nbsp; &nbsp; &nbsp; 'dsi.backend.DEVICES',&nbsp; &nbsp; &nbsp; 'dsi.backend.ORGANISATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.ACCESS',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.CDN',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.frontend.MANAGE',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.frontend.INTERACTIONS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.HELP',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SERVICES',&nbsp; &nbsp; &nbsp; 'dsi.frontend.PROFILE',&nbsp; &nbsp; &nbsp; 'dsi.backend.ACCESS',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.db.ORGANISATION',&nbsp; &nbsp; &nbsp; 'dsi.cache.SEARCH',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.CDN',&nbsp; &nbsp; &nbsp; 'dsi.frontend.OIDC',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.frontend.OIDC',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.HELP',&nbsp; &nbsp; &nbsp; 'dsi.db.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.db.ORGANISATION',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.CDN',&nbsp; &nbsp; &nbsp; 'dsi.frontend.INTERACTIONS',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.frontend.PUBLIC-API',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; &nbsp; 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.ACCESS',&nbsp; &nbsp; &nbsp; 'dsi.backend.ORGANISATIONS',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.frontend.PROFILE',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.frontend.INTERACTIONS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.HELP',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SERVICES',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SUPPORT',&nbsp; &nbsp; &nbsp; 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.backend.ORGANISATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.ACCESS',&nbsp; &nbsp; &nbsp; 'dsi.cache.SEARCH',&nbsp; &nbsp; &nbsp; 'dsi.frontend.CDN',&nbsp; &nbsp; &nbsp; 'dsi.frontend.OIDC',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.frontend.SUPPORT',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.frontend.PROFILE',&nbsp; &nbsp; &nbsp; 'dsi.frontend.INTERACTIONS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.HELP',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SERVICES',&nbsp; &nbsp; &nbsp; 'dsi.frontend.OIDC',&nbsp; &nbsp; &nbsp; 'dsi.cache.SEARCH',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; &nbsp; 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.backend.ORGANISATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.DEVICES',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.ACCESS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.CDN',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.frontend.SERVICES',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.frontend.PROFILE',&nbsp; &nbsp; &nbsp; 'dsi.frontend.INTERACTIONS',&nbsp; &nbsp; &nbsp; 'dsi.frontend.HELP',&nbsp; &nbsp; &nbsp; 'dsi.frontend.SUPPORT',&nbsp; &nbsp; &nbsp; 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.backend.ORGANISATIONS',&nbsp; &nbsp; &nbsp; 'dsi.backend.ACCESS',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.cache.SEARCH',&nbsp; &nbsp; &nbsp; 'dsi.db.ORGANISATION',&nbsp; &nbsp; &nbsp; 'dsi.frontend.OIDC',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; &nbsp; 'dsi.db.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.db.ORGANISATION',&nbsp; &nbsp; &nbsp; 'dsi.frontend.CDN',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.frontend.CDN',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': []&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.backend.ACCESS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.db.ORGANISATION',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.db.ORGANISATION',&nbsp; &nbsp; &nbsp; 'dsi.db.ORGANISATION',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.backend.SAML-ASSERTIONS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.backend.ACCESS',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.backend.DEVICES',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.frontend.CDN',&nbsp; &nbsp; &nbsp; 'dsi.db.DEVICES',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.db.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.backend.ORGANISATIONS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.db.AUDIT',&nbsp; &nbsp; &nbsp; 'dsi.db.ORGANISATION',&nbsp; &nbsp; &nbsp; 'dsi.backend.DIRECTORIES',&nbsp; &nbsp; &nbsp; 'dsi.cache.REDIS',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.backend.sa',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': [&nbsp; &nbsp; &nbsp; 'dsi.backend.APPLICATIONS',&nbsp; &nbsp; ]&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.A-FORMS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.ASP',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.COLLECT',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.DQT',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.GIAS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.INFORMATION-EXCHANGE',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.KEY-TO-SUCCESS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.KEY-TO-SUCCESS_SECURE-ACCESS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.psp',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.saml.SCHOOL-2-SCHOOL',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': samlDeps&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.db.AUDIT',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': []&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.db.DIRECTORIES',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': []&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.db.ORGANISATION',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': []&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.db.DEVICES',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': []&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.cache.REDIS',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': []&nbsp; },&nbsp; {&nbsp; &nbsp; 'name': 'dsi.cache.SEARCH',&nbsp; &nbsp; 'size': 1000,&nbsp; &nbsp; 'imports': []&nbsp; },];var root = packageHierarchy(classes)&nbsp; .sum(function(d) {&nbsp; &nbsp; return d.size;&nbsp; });cluster(root);group = group&nbsp; .data(root.descendants().filter(function(d) {&nbsp; &nbsp; return d.height === 1;&nbsp; }))&nbsp; .enter()&nbsp; .append('text')&nbsp; .each(function(d) {&nbsp; &nbsp; d.angle = (d3.sum(d.children, function(v) {&nbsp; &nbsp; &nbsp; return v.x;&nbsp; &nbsp; }) / d.children.length);&nbsp; &nbsp; d.radius = d3.max(d.children, function(v) {&nbsp; &nbsp; &nbsp; return v.y;&nbsp; &nbsp; }) + 140;&nbsp; })&nbsp; .classed("group", true)&nbsp; .attr('x', function(d) {&nbsp; &nbsp; return Math.sin(d.angle) * d.radius;&nbsp; })&nbsp; .attr('y', function(d) {&nbsp; &nbsp; return -Math.cos(d.angle) * d.radius;&nbsp; })&nbsp; .attr("text-anchor", function(d) {&nbsp; &nbsp; return d.angle < Math.PI ? "start" : "end";&nbsp; })&nbsp; .text(function(d) {&nbsp; &nbsp; return d.data.key.toUpperCase();&nbsp; });link = link&nbsp; .data(packageImports(root.leaves()))&nbsp; .enter().append("path")&nbsp; .each(function(d) {&nbsp; &nbsp; d.source = d[0], d.target = d[d.length - 1];&nbsp; })&nbsp; .attr("class", "link")&nbsp; .attr("d", line);node = node&nbsp; .data(root.leaves())&nbsp; .enter().append("text")&nbsp; .attr("class", "node")&nbsp; .attr("dy", "0.31em")&nbsp; .attr('x', function(d) {&nbsp; &nbsp; return Math.sin(d.x) * d.y;&nbsp; })&nbsp; .attr('y', function(d) {&nbsp; &nbsp; return -Math.cos(d.x) * d.y;&nbsp; })&nbsp; .attr("transform", function(d) {&nbsp; &nbsp; const angle = (d.x * 180 / Math.PI) - 90 + (d.x < Math.PI ? 0 : 180);&nbsp; &nbsp; const x = Math.sin(d.x) * d.y;&nbsp; &nbsp; const y = -Math.cos(d.x) * d.y&nbsp; &nbsp; return "rotate(" + angle + "," + x + "," + y + ")";&nbsp; })&nbsp; .attr("text-anchor", function(d) {&nbsp; &nbsp; return d.x < Math.PI ? "start" : "end";&nbsp; })&nbsp; .text(function(d) {&nbsp; &nbsp; return d.data.key;&nbsp; })&nbsp; .on("mouseover", mouseovered)&nbsp; .on("mouseout", mouseouted);function mouseovered(d) {&nbsp; node&nbsp; &nbsp; .each(function(n) {&nbsp; &nbsp; &nbsp; n.target = n.source = false;&nbsp; &nbsp; });&nbsp; link&nbsp; &nbsp; .classed("link--source", function(l) {&nbsp; &nbsp; &nbsp; if (l.target === d) return l.source.source = true;&nbsp; &nbsp; })&nbsp; &nbsp; .classed("link--target", function(l) {&nbsp; &nbsp; &nbsp; if (l.source === d) return l.target.target = true;&nbsp; &nbsp; })&nbsp; &nbsp; .filter(function(l) {&nbsp; &nbsp; &nbsp; return l.target === d || l.source === d;&nbsp; &nbsp; })&nbsp; &nbsp; .raise();&nbsp; node&nbsp; &nbsp; .classed("node--target", function(n) {&nbsp; &nbsp; &nbsp; return n.target;&nbsp; &nbsp; })&nbsp; &nbsp; .classed("node--source", function(n) {&nbsp; &nbsp; &nbsp; return n.source;&nbsp; &nbsp; });}function mouseouted(d) {&nbsp; link&nbsp; &nbsp; .classed("link--target", false)&nbsp; &nbsp; .classed("link--source", false);&nbsp; node&nbsp; &nbsp; .classed("node--target", false)&nbsp; &nbsp; .classed("node--source", false);}// Lazily construct the package hierarchy from class names.function packageHierarchy(classes) {&nbsp; var map = {};&nbsp; function find(name, data) {&nbsp; &nbsp; var node = map[name],&nbsp; &nbsp; &nbsp; i;&nbsp; &nbsp; if (!node) {&nbsp; &nbsp; &nbsp; node = map[name] = data || {&nbsp; &nbsp; &nbsp; &nbsp; name: name,&nbsp; &nbsp; &nbsp; &nbsp; children: []&nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; if (name.length) {&nbsp; &nbsp; &nbsp; &nbsp; node.parent = find(name.substring(0, i = name.lastIndexOf(".")));&nbsp; &nbsp; &nbsp; &nbsp; node.parent.children.push(node);&nbsp; &nbsp; &nbsp; &nbsp; node.key = name.substring(i + 1);&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return node;&nbsp; }&nbsp; classes.forEach(function(d) {&nbsp; &nbsp; find(d.name, d);&nbsp; });&nbsp; return d3.hierarchy(map[""]);}// Return a list of imports for the given array of nodes.function packageImports(nodes) {&nbsp; var map = {},&nbsp; &nbsp; imports = [];&nbsp; // Compute a map from name to node.&nbsp; nodes.forEach(function(d) {&nbsp; &nbsp; map[d.data.name] = d;&nbsp; });&nbsp; // For each import, construct a link from the source to target node.&nbsp; nodes.forEach(function(d) {&nbsp; &nbsp; if (d.data.imports) d.data.imports.forEach(function(i) {&nbsp; &nbsp; &nbsp; imports.push(map[d.data.name].path(map[i]));&nbsp; &nbsp; });&nbsp; });&nbsp; return imports;}.node,.group {&nbsp; font: 300 11px "Helvetica Neue", Helvetica, Arial, sans-serif;&nbsp; fill: #444;}.group {&nbsp; font-size: 16px;}.node:hover {&nbsp; fill: #000;}.link {&nbsp; stroke: steelblue;&nbsp; stroke-opacity: 0.5;&nbsp; fill: none;&nbsp; pointer-events: none;&nbsp; stroke-width: 1px;&nbsp; stroke-linecap: round;}.node:hover,.node--source,.node--target {&nbsp; font-weight: 700;}/* text color */.node--source {&nbsp; fill: red;}.node--target {&nbsp; fill: blue;}.node--target.node-source {&nbsp; fill: green;}.link--source,.link--target {&nbsp; stroke-opacity: 1;&nbsp; stroke-width: 2px;}/* line color */.link--source {&nbsp; stroke: red;}.link--target {&nbsp; stroke: blue;}.link--source.link--target {&nbsp; stroke: green;}<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript