0

I am trying to zoom based off of a brush made in d3. I have having issues implementing it because it gives me the error this.x.invert is not a function I am not sure why I get the error because they use the same function on the last example here... https://www.d3-graph-gallery.com/graph/interactivity_zoom.html Please can you check my code around line 88. I am trying to find the proper way of Implementing this. Thank you for the help


  private initSvg() {
    const svg = d3.select('svg');
    this.width = +svg.attr('width') - this.margin.left - this.margin.right;
    this.height = +svg.attr('height') - this.margin.top - this.margin.bottom;
    this.g = svg
      .append('g')
      .attr(
        'transform',
        'translate(' + this.margin.left + ',' + this.margin.top + ')'
      );

    const zoomFn = d3.zoom().on('zoom', function (event, d) {
      svg.attr('transform', event.transform);
    });

    this.initAxis();
console.log(this.x);
    // svg.call(zoomFn);
    svg.call(
      d3
        .brush()
        .extent([
          [0, 0],
          [this.width, this.height],
        ])
        .on('start brush', function (event, d) {
          // funcstart
          const extent = event.selection;
          function idled() {
            this.idleTimeout = null;
          }
          console.log('this.x1', this.x);

          function scaleBandInvert(scale) {
            var domain = scale.domain();
            var paddingOuter = scale(domain[0]);
            var eachBand = scale.step();
            return function (value) {
              var index = Math.floor(((value - paddingOuter) / eachBand));
              return domain[Math.max(0, Math.min(index, domain.length - 1))];
            };
          }

          // If no selection, back to initial coordinate. Otherwise, update X axis domain
          if (!extent) {
            if (!this.idleTimeout) {
              return this.idleTimeout = setTimeout(idled, 350); // This allows to wait a little bit
            }
            this.x.domain([ 4, 8]);
            this.x.domain(STATISTICS.map((d) => d.letter));
          } else {
//line 88
            this.x.domain([scaleBandInvert(extent[0]), scaleBandInvert(extent[1]) ]);
            d3.select('.brush').call(brush.move, null); // This remove the grey brush area as soon as the selection has been done
          }

          this.g.transition().duration(1000).call(d3Axis.axisBottom(this.x));
          this.g.selectAll('.bar')
            .transition()
            .duration(1000)
            .attr('cx', function (d) {
              return this.x(d.letter);
            })
            .attr('cy', function (d) {
              return this.y(d.frequency);
            });
        })

      //func end
    );
  }



  private initAxis() {
    this.x = d3Scale.scaleBand().rangeRound([0, this.width]).padding(0.1);
    this.y = d3Scale.scaleLinear().rangeRound([this.height, 0]);
    this.x.domain(STATISTICS.map((d) => d.letter));
    this.y.domain([0, d3Array.max(STATISTICS, (d) => d.frequency)]);
  }

joey
  • 115
  • 8
  • Band scales do not have an invert method, though there are alternative ways of inverting values [eg](https://stackoverflow.com/q/38633082/7106086) – Andrew Reid Jul 05 '21 at 05:43
  • @AndrewReid I have updated my code with the scaleBandInvert function. But I am still stuck. Do you think you can give me some tips and if my approach is correct? – joey Jul 05 '21 at 14:27
  • @joey Have you managed to adapt this code to TypeScript that you can use in your Angular app? – CatarinaRuna Oct 21 '21 at 10:21

0 Answers0