javascript - d3.js : Applying styles to individual lines

标签 javascript svg d3.js

正在尝试 draggable network 并希望能够对不同的链接使用不同的颜色。当我注释掉这些行时

/*var link = svg.append("g")
    .attr("class", "link") 
    .selectAll("line");*/

并将其替换为 var link = svg.append("g");
这样我就可以尝试逐个添加链接,并使用 if-else 条件,在其中我可以对每一行应用不同的线条样式。但是,当我尝试将单一样式统一应用于所有线条本身时,线条并未显示在屏幕上。 Firebug也没有显示任何错误。

  link = link.data(graph.links).enter().append("line")
      .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; })
      .attr("class", "link");

我添加了 .attr("class", "link"); 部分,认为它会将样式应用于线条。但事实并非如此。您能帮助我们找到有选择地附加属性的正确方法吗?

这是完整的代码:

<!DOCTYPE html>
<meta charset="utf-8">

<svg id="mySvg" width="20" height="20">
  <defs id="mdef">
        <pattern id="image" x="0" y="0" height="20" width="20">
          <image x="0" y="0" width="20" height="20" xlink:href="url.png"></image>
        </pattern>
  </defs>
  <defs>
  <pattern id="tile-ww" patternUnits="userSpaceOnUse" width="25" height="25">
  <image xlink:href="url.png" x="15" y="15" width="15" height="15"></image></pattern>
  </defs>
</svg>

<style>

.node {
  stroke: green;
  stroke-width: 1px;
  opacity: 0.8;
  fill: url(#image);  
}

.node .selected {
  stroke: red;
}

.link {
  stroke: orange;
  stroke-width: 3;
  stroke-dasharray: 20,10,5,5,5,10;
  opacity: 0.5;
}

.dotted {border: 1px dotted #ff0000; border-style: none none dotted; color: #fff; background-color: #fff; }

.brush .extent {
  fill-opacity: .1;
  stroke: #fff;
  shape-rendering: crispEdges;
}

</style>
<body>
<script src="d3/d3.v3.js"></script>

<script>

var width = 960, height = 500, shiftKey;

var svg = d3.select("body")
    .attr("tabindex", 1)
    .on("keydown.brush", keydown)
    .on("keyup.brush", keyup)
    .each(function() { this.focus(); })
    .append("svg")
    .attr("width", width)
    .attr("height", height);

/*var link = svg.append("g")
    .attr("class", "link") 
    .selectAll("line");*/
var link = svg.append("g");

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

var node = svg.append("g")
    .attr("class", "node")
    .selectAll("circle");

//Add the SVG Text Element to the svgContainer
text = svg.append('text').text('This is some information about whatever')
                        .attr('x', 50)
                        .attr('y', 200)
                        .attr('fill', 'black');

//you can delete this circle
svg.append("circle")
         .attr("class", "logo")
         .attr("cx", 225)
         .attr("cy", 225)
         .attr("r", 20)
         .style("fill", "transparent")       
         .style("stroke", "black")     
         .style("stroke-width", 0.25)
         .on("mouseover", function(){ 
               d3.select(this)
                   .style("fill", "url(#image)");
         })
          .on("mouseout", function(){ 
               d3.select(this)
                   .style("fill", "transparent");
         });

//get the json file with either error messages or the entire data as "graph" object
d3.json("graph.json", function(error, graph) {

  //"links" is a property in "graph", and contains some data in it. Iterate through all of them
  graph.links.forEach(function(d) //iterate through each data object in link
  {
    d.source = graph.nodes[d.source];//we got nodes too, with graph so access its data
    d.target = graph.nodes[d.target];
    d.linkStatus = d.status;
    console.log(d.source);
  });


  link = link.data(graph.links).enter().append("line")
      .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; })
      .attr("class", "link");

  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);
        }));

  node = node.data(graph.nodes).enter().append("circle")
      .attr("r", 10)//radius
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; })
      .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(d3.behavior.drag()
        .on("drag", function(d) { nudge(d3.event.dx, d3.event.dy); }));
});

function nudge(dx, dy) 
{
  node.filter(function(d) { return d.selected; })
      .attr("cx", function(d) { return d.x += dx; })
      .attr("cy", function(d) { return d.y += dy; })

  link.filter(function(d) { return d.source.selected; })
      .attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; });

  link.filter(function(d) { return d.target.selected; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

  d3.event.preventDefault();
}

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>

最佳答案

您不需要任何 if-else 条件,也不需要对现有代码进行大量修改。在 D3 中设置线条颜色等内容的方式是通过 .style() 命令:

link.style("stroke", ...);

参数不必是固定值,但可以是函数。然后针对选择中的每个元素(在本例中为线条)评估此函数,从而允许您为它们赋予不同的颜色。例如,如果您想根据源的 x 位置提供不同的颜色,您将执行以下操作。

var color = d3.scale.category20();
link.style("stroke", function(d) { return color(d.source.x); });

您可以使用绑定(bind)到元素的数据中的任何内容 (d) 来确定您想要的颜色,或者其他任何颜色。例如根据索引为每行设置不同的颜色,您可以这样做。

link.style("stroke", function(d, i) { return color(i); });

关于javascript - d3.js : Applying styles to individual lines,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22142209/

相关文章:

javascript - 设置 JavaScript 变量以便稍后检查定义

javascript - 试图获得预期效果的问题

javascript - D3 : zoom to bounding box with d3-tiles

css - 为 SVG 图像添加边框

javascript - 如何获取沿饼图边缘的切片坐标?

javascript - 用虚线显示缺失值

javascript - 访问数据列表中值以外的其他参数

php - Wordpress 将短代码插入菜单项

javascript - 使用 jQuery 嵌入上传的 svg

javascript - 如何使用 Enter()、exit() 和更新水平 "stacked"图表