【问题标题】:d3 scaleLinear update and zoom conflictd3 scaleLinear更新和缩放冲突
【发布时间】:2018-02-27 13:44:55
【问题描述】:

我在 d3 中结合手动更新和缩放功能时遇到问题。

这是一个从一个较大的模块中截取的小演示代码,它只创建一个线性比例。

https://jsfiddle.net/superkamil/x3v2yc7j/2

class LinearScale {
  constructor(element, options) {
    this.element = d3.select(element);
    this.options = options;

    this.scale = this._createScale();
    this.axis = this._createAxis();
    this.linearscale = this._create();
  }

  update(options) {
    this.options = Object.assign(this.options, options);

    this.scale = this._createScale();
    this.axis = this._createAxis();

    this.linearscale.call(this.axis);
  }

  _create() {
    const scale = this.element
    .append('g')
    .attr('class', 'linearscale')
    .call(this.axis);

    this.zoom = d3.zoom().on('zoom', () => this._zoomed());

    this.element.append('rect')
      .style('visibility', 'hidden')
      .style('width', this.options.width)
      .style('height', this.options.height)
      .attr('pointer-events', 'all')
      .call(this.zoom);

    return scale;
  }

  _createScale() {
    let range = this.options.width;

    this.scale = this.scale || d3.scaleLinear();

    this.scale.domain([
      this.options.from,
      this.options.to
    ]).range([0, range]);

    return this.scale;
  }

  _createAxis() {
    if (this.axis) {
      this.axis.scale(this.scale);
      return this.axis;
    }

    return d3.axisBottom(this.scale);
  }

  _zoomed() {     
    this.linearscale
      .call(this.axis.scale(d3.event.transform.rescaleX(this.scale)));

    let domain = this.axis.scale().domain();

    this.element.dispatch('zoomed', {
      detail: {
        from: domain[0],
        to: domain[1],
      },
    });
  }
}

const scale = new LinearScale(document.getElementById('axis'), {
  from: 0,
  to: 600,
  width: 600,
  height: 100
});

document.getElementById('set').addEventListener('click', () => {
  scale.update({
    from: 0,
    to: 100
  });
});
  1. 将 x 轴缩小到 0 - 10000(随机数)
  2. 点击“设置”按钮
  3. X 轴将域设置为 0 - 100
  4. 再次开始缩小

-> 预期:缩放从域 0 - 100 开始

-> 结果:缩放跳回到之前的缩放级别 0 - 10000

我知道,d3 正在使用比例副本,我正在更新原始比例,但我没有找到如何组合它们或如何将缩放级别设置为原始比例的方法。

https://github.com/d3/d3-zoom/blob/master/README.md#transform_rescaleX

谢谢!

【问题讨论】:

  • 当我按下“设置”按钮时,我得到了 0-100。
  • 问题后来出现在“4. 再次开始缩小”。但现在已经修好了。看看 Cosma 的回答。

标签: javascript html d3.js


【解决方案1】:

您要么重新创建缩放行为,要么只是重置当前的缩放变换。 您应该能够重置每个参数(缩放和平移)或将它们全部重置。以下示例还触发了缩放特定事件,但由于您已经设置了域,因此应该不是视觉问题。

例如: 添加 this.element.select("rect").call(this.zoom.transform, d3.zoomIdentity); 在您的更新功能中。

https://github.com/d3/d3-zoom/blob/master/README.md#zoom_transform 中有关缩放 api 的更多信息。我还在 https://bl.ocks.org/mbostock/db6b4335bf1662b413e7968910104f0f 找到了一个使用过渡动画的示例。 我还更新了小提琴:

update(options) {

  this.options = Object.assign(this.options, options);
  this.scale = this._createScale();
  this.axis = this._createAxis();

  this.linearscale.call(this.axis);
  this.element.select("rect").call(this.zoom.transform, d3.zoomIdentity);
}

https://jsfiddle.net/x3v2yc7j/8/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    相关资源
    最近更新 更多