Search code examples
javascriptd3.jszooming

D3.js how to create this zoom behavior?


I want my chart's xAxis to behave like this when zooming using mousewheel. Expected behavior: Expected behavior

My current zoom

const zoomExtent = [ [ 0, 0 ], [ innerWidth, innerHeight ] ]
const xScale = scaleUtc().domain(minMaxData).range([0, innerWidth])

const handleZoom  = ({ transform }) => {
  transform.rescaleX(xScale)
}

const zoomBehavior = zoom().scaleExtent([ 0.4, 4 ]).extent(zoomExtent).translateExtent(zoomExtent).on('zoom', handleZoom)

This is my chart with d3 default behavior with d3 default behavior

My questions:

  1. How to always focus the zoom to the right edges (the latest data on the chart) instead of where the mouse currently at?
  2. How to prevent x axis from expanding to the right that causing my latest data (at the right edge) to leave the view port ?

Solution

  • This is not an elegant solution but it worked.

    // check if wheeled
    const isWheeled = sourceEvent.type === 'wheel'
    
    // i need it to be infinite because i lazy load the older data.
    // there is no middle infinity.
    const zoomExtent = [ [ Infinity, 0 ], [ innerWidth, innerHeight ] ]
    
    // fix focal point at the innerwidth. using previous transform
    const tx = innerWidth - transform.invertX(innerWidth) * k
    const myZoom = zoomIdentity.translate(isWheeled ? tx : x, 0).scale(k)
    
    // prevent jumping when dragging
    sourceEvent.target.__zoom = myZoom
    
    // update scale
    const handleZoom  = ({ transform }) => {
      myZoom.rescaleX(xScale)
    }
    

    If you have better solution pls let me know.