【问题标题】:SVG Translate Group positioning on window resize with d3SVG 翻译组在使用 d3 调整窗口大小时定位
【发布时间】:2017-10-25 21:12:06
【问题描述】:

在使用 d3 enter, update 模式时,我看到一些奇怪的转换行为。我创建了一组 (svg:g) 文本 (svg:text) 项目。当我最初使用.enter.append('g').attr('transform',function(d){...translate...} 创建组时,这些项目相对于 SVG 的顶部。但是,当我在窗口调整大小后更新组时,组是相对于它们最外层的容器的。

我的数据是一组嵌套的对象 (d3.nest)

var myData=[{
    key:f,
    values:[{
      group:f,
      text:'foo'
    }]
  },
  {
    key:b,
    values:[{
      group:'b',
      text:'bar'
    },{
      group:'b',
      text:'baz'
    }]
  }
.....
]

我的输入/更新模式是:

// EDIT Some JS to add shapes first
var shapeCont = d3.select('#shapesAtTheTop');
var shapes = shapeCont.selectAll('rect')
  .data([50,50]);
shapes.exit().remove();
shapes.enter().append('rect')
  .attr('width',function(d){return window.innerWidth*(d/100)})
  .attr('x', function(d,i){return i*window.innerWidth*(d/100)})
  .attr('y',0)
  .attr('height',95);
// END EDIT
// Now add the text
var textgroupLeft = window.width/50, textGrouptop = 100;
function translateGroup(datum, i){
  var x = textGroupLeft * i;
  var y = textGroupTop;
  return 'translate('+x+' '+y+')';
}
var textContainer = d3.select('g.textContainer');
var txtg = textContainer.selectAll('g').data(myData,function(d){return d.key;});
// UPDATE
txtg.attr('transform',translateGroup);
// REMOVE
txtg.exit().remove();
// NEW
txtg.enter().append('g')
  .classed('textGroup',true')
  .attr('transform',transelateGroup)

var txt = d3.selectAll('g.textGroup').selectAll('text')
  .data(function(d){retrun d.values;},
    function(dataum){return JSON.stringify(dataum);})
// REMOVE
.....
// UPDATE
.....
// NEW
.....

我的 HTML/SVG 是:

<svg>
  <g id="shapesAtTop">
  ..... add polygons with positions in the first 100px high ....
  </g>
  <g id="textBelow" class="textContainer">
  </g>
</svg>

是切换坐标系吗?如果是,为什么?

【问题讨论】:

  • var textgroupLeft = window.width/50: 你是在某处定义了 window.width 还是需要 window.innerWidth?
  • 您在发布的代码中也有一些拼写错误,使用 retrun 和 transelateGroup 而不是 return 和 translateGroup 尽管您的代码运行我想它们在您的实际代码中不存在。
  • 抱歉有错别字。我不得不在单独的工作站上重新输入。 Window.innerwidth 就是我的意思。

标签: javascript d3.js svg transform


【解决方案1】:

很难看出哪里出错了。您可以通过在 HTML 中或使用 D3 以编程方式在 SVG 中的 #textBelow 组上显式定义翻译来解决此问题。一旦该组具有正确的垂直位置,就可以更轻松地平移任何嵌套对象。

很难遵循您确定要应用的翻译的代码。我建议使用 d3 BandScale 来处理从要转换的对象的索引到像素值的映射。

下面的 sn-p 使用 D3 v4 演示了这两个。如果您需要使用 D3 的早期版本,那么刻度的名称会有所不同,并且您必须更加小心 selection.enter(),因为您没有得到 selection.merge() 方法。

var data = [{key:'a'}, {key:'b'}]
var width = 500 //px

update(data,width)
setTimeout(function (){update(data,200)}, 2000)

function update(data, width) {
  //create a band scale to assist with layout
  var scale = d3
    .scaleBand()
    .domain(d3.range(data.length))
    .range([0, width])
    // padding ratio of total width
    .padding(0.1);

  // append/modify shapes
  var shapeCont = d3.select("#shapesAtTop");
  var shapes = shapeCont.selectAll("rect").data(data);
  // remove any unused nodes
  shapes.exit().remove();
  // enter
  shapes.enter()
    // add new rectangles
    .append("rect")
    // merge selection with any existing nodes
    .merge(shapes)
    // set all rect attributes
    .attr("x", function(d, i) {
      return scale(i);
    })
    .attr("y", 0)
    .attr("height", 95)
    .attr("width", scale.bandwidth());

  //append/modify text group elements
  var textContainer = d3.select('#textBelow');
  var txtg = textContainer.selectAll('g')
    .data(data, function(d) {
      return d? d.key : this.id
    });
  // remove any unused nodes
  txtg.exit().remove()
  // enter
  txtg.enter()
    .append('g')
    .classed('textGroup', true)
    // add some text to new elements
    .call( function (g) { g.append('text').text('I am text')})
    // merge exisiting and new
    .merge(txtg)
    .attr('transform', function(d, i) {
      return 'translate(' + scale(i) + ')'
    })
}
svg {
  width: 100%;
  height: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
<svg>
  <g id="shapesAtTop">
  </g>
  <g id="textBelow" class="textContainer" transform="translate(0,120)">
  </g>
</svg>

【讨论】:

  • 将转换添加到最外层的g 似乎可行,但为什么需要这样做?在考虑了一段时间之后。在我看来,当页面加载“shapesAtTop”时,“shapesAtTop”的尺寸为 0x0(H&W),因此页面基于该 0x0 流动。然后,当调整大小时,shapesAtTop 的高度不为零,从而将组向下推。
猜你喜欢
  • 2013-04-22
  • 2022-06-10
  • 2021-04-09
  • 2012-11-17
  • 2012-12-21
  • 2019-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多