2017-10-06 58 views
1

我想在我的d3(v4)图表中实现缩放和刷牙。如何重置/删除存储在d3 v4元素中的缩放变换?

我已经得到了他们两个单独工作,但我试图在同一个图表上实现这两个功能时出现问题。我的场景如下: 1.用户使用画笔显示图表的特定区域。 2.然后,他们缩放/平移,但这会导致视图跳回旧位置,因为存储的缩放转换不知道刷牙所做的更改。

我的理解是,当前缩放变换(比例+平移)存储在DOM元素内部的__zoom属性中。无论何时与元素交互(例如通过滚动鼠标滚轮),缩放插件都会自动调整此功能。

我看到你可以使用d3.zoomTransform得到一个元素的当前缩放变换。

如何重置/移除存储的缩放变换(例如,在平移之后,以便随后的任何缩放都从刷牙停止的位置继续进行)?

注意:我不想改变缩放,而只是更新存储的缩放变换,将新的缩放比例视为“身份”。这很重要,因为我想刷牙时等

+0

你解决了吗?我有同样的问题! –

+1

@AralRoca我已经添加了一个答案,显示我最终做了什么 –

回答

2

我到底解决这个得到的方式能够顺利过渡,从一个规模到另一个是:

    在缩放处理
  1. ,使用transform.rescaleX()来获得基于变换规模
  2. 更新x轴的基础上,规模
  3. 重置转换元件d3.zoomIdentity上一个新的变换尺度
  4. 更新主刻度的域。

这里关键的是,在缩放比例更新之后,DOM元素上存储的变换总是被放回到标识(即scale = 1,translate = 0,0)。

这意味着我们不需要担心刷牙/缩放或对不同元素上的刻度进行的任何编程式更改都不会相互冲突或具有不同的值。我们有效地继续使用非常小的比例因子。

在代码示例而言,这里是从我的工作表的相关部分:

// class contains: 
// this.xScale - stored scale for x-axis 
// this.xAxis - a d3 Axis 
// this.xAxisElement - a d3 selection for the element on which the x-axis is drawn 
// this.zoomX - a d3 ZoomBehavior 
// this.chartElement - a d3 selection for the element on which the zooming is added 

protected setupZooming(): void { 
    this.zoomX = d3.zoom().on('zoom',() => { this.onZoomX(); }); 

    this.zoomXElement = this.xAxisElement 
    .append('rect') 
     .attr('fill', 'none') 
     .style('pointer-events', 'all') 
     .attr('width', this.width) 
     .attr('height', this.margin.bottom) 
     .call(this.zoomX); 
} 

onZoomX(): void { 
    const transform: d3.ZoomTransform = d3.event.transform; 

    if (transform.k === 1 && transform.x === 0 && transform.y === 0) { 
    return; 
    } 

    const transformedXScale = transform.rescaleX<any>(this.xScale); 

    const from = transformedXScale.domain()[0]; 
    const to = transformedXScale.domain()[1]; 

    this.zoomXTo(from, to, false); 

    this.chartElement.call(this.zoomX.transform, d3.zoomIdentity); 
} 

zoomXTo(x0: Date, x1: Date, animate: boolean): void { 
    const transitionSpeed = animate ? 750 : 0; 

    this.xScale.domain([x0, x1]); 

    this.xAxisElement.transition().duration(transitionSpeed).call(this.xAxis); 
    this.updateData(transitionSpeed); 
} 

updateData(transitionSpeed: number): void { 
    // ... 
} 

道歉,如果这种提取物是不容易的外面跟随我的代码,其余的背景下,但希望它仍然有帮助。