【问题标题】:Svg image representing a node, varying node size in a force-directed graph表示节点的 Svg 图像,在力导向图中改变节点大小
【发布时间】:2012-09-05 19:45:16
【问题描述】:

到目前为止,我在一个力导向图中使用了 d3.svg.symbol() 来区分不同的节点类型。

我现在想通过将节点显示为 svg 图像来区分不同的节点类型。在examples 之一之后,我使用以下代码显示节点图像:

    var node = svg.selectAll("image.node").data(json.nodes);
    var nodeEnter = node.enter().append("svg:g").append("svg:image")
    .attr("class", "node")
    .attr("xlink:href", function(d)
    {
      switch( d.source )
      {
        case "GEXP": return "img/node_gexp.svg";
        case "CNVR": return "img/node_cnvr.svg";
        case "METH": return "img/node_meth.svg";
        case "CLIN": return "img/node_clin.svg";
        case "GNAB": return "img/node_gnab.svg";
        case "MIRN": return "img/node_mirn.svg";
        case "SAMP": return "img/node_samp.svg";
        case "RPPA": return "img/node_rppa.svg";
      }
    })
    .attr("x", function(d) { return d.px; } )
    .attr("y", function(d) { return d.py; } )
    .attr("width", "50")
    .attr("height", "50")
    .attr("transform", "translate(-25,-25)")
    .on("click", function(d) { 
      console.log("nodeclick");
      } )
    .on("mouseover", fade(0.10) )
    .on("mouseout", fade(default_opacity) )
    .call(force.drag);

这确实显示了 svg 图片,但我有两个问题:

1) 我想根据属性缩放节点大小。据我了解,这可以通过提供“比例”属性来完成

transform="scale(something)"

到一个合适的地方,比如图片标签本身或者包含图片的组:

    var node = svg.selectAll("image.node").data(json.nodes);
    var nodeEnter = node.enter()
    .append("svg:g")
    .attr("transform", function(d) 
    {
      var str = "scale(";
        if( d.gene_interesting_score && d.gene_interesting_score > 0 )
        {
          return str + ( (d.gene_interesting_score - minScore ) / ( maxScore - minScore ) ) + ")";
        }
        return str + 0.7 + ")";
    })
    .append("svg:image")
    ....

当它发生时, scale() 变换会置换图像:它们不再位于边缘的端点上。初始化图形时如何正确调整图像大小,最好使控制机制在单个函数中(例如,这样我就不必分别控制 x、y、width、height)?

2) 缩放图表时,Chrome 会模糊图像,而在 Firefox 中,图像仍然清晰(图片)。如何避免这种模糊?

编辑:根据 duopixel 的建议,代码如下:

    var nodeGroup = svg.selectAll("image.node").data(json.nodes).enter()
    .append("svg:g")
    .attr("id", function(d) { return d.id; }) 
    .attr("class", "nodeGroup")
    .call(force.drag);

    var node = nodeGroup.append("svg:image")
    .attr("viewBox", "0 0 " + nodeImageW + " " + nodeImageH)
    .attr("class", "node")
    .attr("xlink:href", function(d)
    {
      switch( d.source )
      {
        case "GEXP": return "img/node_gexp.svg";
        case "CNVR": return "img/node_cnvr.svg";
        case "METH": return "img/node_meth.svg";
        case "CLIN": return "img/node_clin.svg";
        case "GNAB": return "img/node_gnab.svg";
        case "MIRN": return "img/node_mirn.svg";
        case "SAMP": return "img/node_samp.svg";
        case "RPPA": return "img/node_rppa.svg";
      }
    })
    .attr("width", nodeImageW)
    .attr("height", nodeImageH)
    .attr("transform", function(d) 
    {
      var matrix = "matrix(";
      var scale = 0.7; // sx & sy
      if( d.gene_interesting_score && d.gene_interesting_score > 0 )
      {
        scale = ( (d.gene_interesting_score - minScore ) / ( maxScore - minScore ) ) * 0.5 + 0.25; 
      }
      //console.log("id=" + d.id + ", score=" + scale );
      matrix += scale + ",0,0," + scale + "," + ( d.x - ( scale*nodeImageW/2 ) ) + "," + ( d.y - ( scale*nodeImageH/2 ) ) + ")";
      return matrix;
    })
    // .attr("transform", "translate(-25,-25)")
    .on("click", function(d) { 
      console.log("nodeclick");
      } )
    .on("mouseover", fade(0.10) )
    .on("mouseout", fade(node_def_opacity) );

它解决了第一个问题,但不是第二个问题:通过选择

var nodeImageH = 300;
var nodeImageW = 300;

生成的 svg 图像包含很多空白空间(通过使用 firebug 的选择工具选择图像可以看到)。这些图像是在 Inkscape 中创建的,画布尺寸裁剪为 50x50,这应该是正确的查看像素尺寸。

【问题讨论】:

    标签: svg graph d3.js force-layout


    【解决方案1】:

    #1 需要设置变换原点。在 SVG 中,这意味着您将不得不使用此处回答的变换矩阵:https://stackoverflow.com/a/6714140/524555

    #2 要解决模糊缩放问题,请将您的 svg 文件的 viewBox, width, height 修改为以大图像开始(即 <svg viewBox="0 0 300 300" width="300" height="300">

    【讨论】:

    • 似乎 #2 不起作用或者我做错了什么,请参阅上面的编辑。
    • 您不能在 image 元素上分配 viewBox,您必须深入研究实际的 svg 文件并更改那里的值。或者只是放大 Inkscape 中的图像(Webkit 本质上将 svg 文件视为位图,因此如果您想保持清晰,则需要更大的版本)。
    猜你喜欢
    • 2015-07-30
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    相关资源
    最近更新 更多