简体   繁体   中英

How to zoom via brush in d3 with non-standart axises

Im trying to do the zooming via brush like in this block https://bl.ocks.org/FrissAnalytics/539a46e17640613ebeb94598aad0c92d

The difference is that I need to define axis values manually due to zooming, cause I need to keep the distance between ticks the same (like scaleOrdinal, but I did it with scaleLinear). Im stuck with the brushing - it works fine when it zoom via brush first time, but if I want to go deeper, the zoom is lagging - the scale is calculating well, but translation goes at any place, but not at right.

There is my fiddle (it is a bit messy, I called getRange several times for defining boundaries) https://jsfiddle.net/Celeritas/y2u06kpm/2/

So I have this code now for brush_end event

function brush_endEvent() {
  const s = d3.event.selection;

  if (!s && lastSelection !== null) {
    //this doing the same thing
    let scaleX = lastTransform.rescaleX(x);
    let scaleY = lastTransform.rescaleY(y);

    gxAxis.call(xAxis.scale(scaleX));
    gyAxis.call(yAxis.scale(scaleY));

    //here I getting the current domain for zoomed area, which will set with the equal distance between ticks
    getRange({
      x1: scaleX.domain()[0],
      x2: scaleX.domain()[scaleX.domain().length - 1],
      y1: scaleY.domain()[0],
      y2: scaleY.domain()[scaleY.domain().length - 1],
    })

    let kWidth = Math.ceil(tickTextWidth / (width / t.length)) + 1
    let kHeight = Math.ceil(tickTextHeight / (height / b.length))

    //im redefining domains manually
    scaleX.domain(t)
    scaleY.domain(b)

    xAxis.tickValues(t.filter((e, i) =>  i % kWidth === 0)).tickFormat(d3.format('d'))
    yAxis.tickValues(b.filter((e, i) =>  i % kHeight === 0)).tickFormat(d3.format('d'))
    xAxis2.tickValues(t.filter((e, i) =>  i % kWidth === 0)).tickFormat(d3.format('d'))
    yAxis2.tickValues(b.filter((e, i) =>  i % kHeight === 0)).tickFormat(d3.format('d'))

    let totalX = Math.abs(lastSelection.x2 - lastSelection.x1);
    const originalPoint = [scaleX.invert(lastSelection.x1), scaleY.invert(lastSelection.y1)];

    const tt = d3.zoomIdentity.scale(((width * lastTransform.k) / totalX));
    // BUT HERE im not doing rescale, cause im already redefine domain earlier
    //scaleX = tt.rescaleX(x);
    //scaleY = tt.rescaleY(y);

    canvasChart
      .transition()
      .duration(200)
      .ease(d3.easeLinear)
      .call(zoom_function.transform,
        d3.zoomIdentity
          .translate(scaleX(originalPoint[0]) * -1, scaleY(originalPoint[1]) * -1)
          .scale(tt.k));
    lastSelection = null;

  } else {
    brushSvg.call(brush.move, null);
  }
}

So Im in despair, I dont getting, how to set zoom to the right position after brushing. Thanks for any help!

d3.zoomIdentity
          .translate(x(originalPoint[0]) * -1, y(originalPoint[1]) * -1)
          .scale(tt.k)

Well, the mistake was in the xy for zoom. It should be original, non-rescaled domain

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM