D3轴标签旋转过渡不顺畅

D3 axis label rotate transition not smooth

本文关键字:标签 旋转 D3      更新时间:2023-09-26

在我的过渡中,一个轴旋转90度,然后标签在相反的方向旋转以保持直立。下面是我想要的一个最小的例子,除了过渡不是那么平滑。如果你仔细观察,你可以看到标签在旋转到位之前向上移动(翻译)。我怎样才能摆脱这种轮班?我已经摆弄了rotatetranslate,但无济于事。

(如果你认为这不是太糟糕,我同意,但由于某种原因,这种转变实际上在我的实际情节中更为明显。)

更新。罪魁祸首是text-anchor属性在middlestart之间来回切换。因为这些是离散的值,我想不出一种简单的方法来在它们之间转换。

var width = 170;
var scale = d3.scaleLinear().domain([0, 5])
  .range([0, width]);
var axis = d3.axisBottom()
  .scale(scale)
  .ticks(6);
var graph = d3.select('svg').append('g')
  .attr('transform', 'translate(10,10)');
graph.append('g')
  .attr('transform', 'translate(0,' + width + ')')
  .call(axis);
var tickLabels = d3.selectAll('text');
var toggle = false;
d3.select('button').on('click', function() {
  toggle = !toggle;
  if (toggle) {
    graph.transition().duration(1000)
      // .attr('transform','rotate(-90)');
      .attr('transform', 'rotate(-90 ' + (width / 2 + 10) + ' ' + (width / 2 + 10) + ')');
    tickLabels.transition().duration(1500).delay(1000)
      .attr("y", 0)
      .attr("x", 9)
      .attr("dy", ".3em")
      .attr("transform", "rotate(90)")
      .style("text-anchor", "start");
  } else {
    graph.transition().duration(1000)
      .attr('transform', 'rotate(0) translate(10,10)');
    tickLabels.transition().duration(1500).delay(1000)
      .attr('y', 9)
      .attr('x', 0.5)
      .attr('dy', '0.71em')
      .attr('transform', 'rotate(0)')
      .style('text-anchor', null);
  }
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width='200' height='200'>
</svg>
<div>
  <button>Rotate</button>
</div>

找到了解决方案,实际上相当简单。关键是在旋转标签之前改变x属性以抵消text-anchor的偏移。结果非常好。

var width = 170;
var scale = d3.scaleLinear().domain([0, 5])
  .range([0, width]);
var axis = d3.axisBottom()
  .scale(scale)
  .ticks(6);
var graph = d3.select('svg').append('g')
  .attr('transform', 'translate(10,10)');
graph.append('g')
  .attr('transform', 'translate(0,' + width + ')')
  .call(axis);
var tickLabels = d3.selectAll('text');
var toggle = false;
d3.select('button').on('click', function() {
  toggle = !toggle;
  if (toggle) {
    graph.transition().duration(1000)
      // .attr('transform','rotate(-90)');
      .attr('transform', 'rotate(-90 ' + (width / 2 + 10) + ' ' + (width / 2 + 10) + ')');
    tickLabels.transition().duration(0).delay(1000)
      .attr('x', -3)
      .style("text-anchor", "start")
      .transition().duration(1000)
      .attr("y", 0)
      .attr("x", 9)
      .attr("dy", ".3em")
      .attr("transform", "rotate(90)");
  } else {
    graph.transition().duration(1000)
      .attr('transform', 'rotate(0) translate(10,10)');
    tickLabels.transition().duration(0).delay(1000)
      .attr('x', 12)
      .style('text-anchor', null)
      .transition().duration(1000)
      .attr('y', 9)
      .attr('x', 0.5)
      .attr('dy', '0.71em')
      .attr('transform', 'rotate(0)');
  }
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width='200' height='200'>
</svg>
<div>
  <button>Rotate</button>
</div>