2017-10-06 54 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 { 
    // ... 
} 

道歉,如果這種提取物是不容易的外面跟隨我的代碼,其餘的背景下,但希望它仍然有幫助。