D3 v4多系列折线图缩放问题

时间:2016-09-12 06:19:36

标签: javascript angularjs d3.js angular

我试图为使用d3和Angular 2构建的多系列折线图添加缩放功能。

ngOnChanges(data):void {
    this.setup(data);
    this.initData(data);
    this.buildSVG();
    this.scaleAxis(data);
    this.populate();
    this.drawXAxis();
    this.drawYAxis();
    this.zoomEventHandler();
    this.addVerticalLineTooltip();
  }

  private setup(data):void {
    this.margin = {top: 50, right: 100, bottom: 100, left: 100};
    this.width = 600;
    this.height = 400;
    this.xScale = d3.scaleTime().range([0, this.width]);
    this.yScale = d3.scaleLinear().range([this.height, 0]);
    this.zScale = d3.scaleOrdinal(d3.schemeCategory10);

    this.zScale.domain(d3.keys(data[0]).filter(function (key) {
      return key !== "date";
    }));
  }

  private initData(data) {
    // format the data
    data.forEach((d)=> {
      d.date = this.parseDate(d.date);
    });

    this.ds = this.zScale.domain().map((name)=> {
      return {
        name: name,
        values: data.map((d) => {
          return {x: d.date, y: d[name], name: name};
        })
      };
    });
  }

  /**
   *  build  SVG element using the configurations
   **/
  private buildSVG():void {
    this.host.html('');

    this.svg = this.host.append('svg')
      .attr('width', this.width + this.margin.left + this.margin.right)
      .attr('height', this.height + this.margin.top + this.margin.bottom)
      .append('g')
      .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');

    this.svg.append('rect')
      .attr('class', 'view')
      .attr('x', 0.5)
      .attr('y', 0.5)
      .attr('width', this.width)
      .attr('height', this.height)
      .style('fill', '#EEEEEE')
      .style('stroke-width', '0px');
  }

  private scaleAxis(data) {
    this.xScale.domain(d3.extent(data, (d) => {
      return d.date;
    }));

    this.yScale.domain([
      d3.min(this.ds, (c) => {
        return d3.min(c.values, function (d) {
          return d.y;
        });
      }),
      d3.max(this.ds, (c) => {
        return d3.max(c.values,
          (d) => {
            return d.y;
          });
      })
    ]);

    this.zScale.domain(this.ds.map((c) => {
      return c.name;
    }));

    this.make_x_axis = ()=> {
      return d3.axisBottom()
        .scale(this.xScale)
        .tickPadding(15);
    };

    this.make_y_axis = ()=> {
      return d3.axisLeft()
        .scale(this.yScale)
        .tickPadding(10);
    };
  }


  /**
   * Create x axis
   **/
  private drawXAxis():void {

    this.xAxis = d3.axisBottom()
      .scale(this.xScale)
      .tickPadding(15);

    this.svg.append('g')
      .attr('class', 'x-axis')
      .attr('transform', 'translate(0,' + this.height + ')')
      .call(this.xAxis);

    this.svg.append('text')
      .attr('text-anchor', 'middle')
      .attr('transform', 'translate(' + (this.width / 2) + "," + (this.height + this.margin.bottom / 2) + ")")
      .text('Date');

  }

  /**
   *create y axis
   **/
  private drawYAxis():void {

    this.yAxis = d3.axisLeft()
      .scale(this.yScale)
      .tickPadding(10);

    this.svg.append('g')
      .attr('class', 'y-axis')
      .call(this.yAxis)
      .append('text')
      .attr('transform', 'rotate(-90)');

    this.svg.append('text')
      .attr('text-anchor', 'middle')
      .attr("transform", "translate(-" + (this.margin.left / 2) + "," + (this.height / 2) + ")rotate(-90)")
      .text('Sales / Searches');

    this.svg.append("g")
      .attr("class", "y grid")
      .call(this.make_y_axis()
        .tickSize(-this.width, 0, 0)
        .tickFormat(""))
      .style("opacity", "0.1");
  }

  /**
   * Populate the graphs
   **/
  private populate():void {
    // define the line
    this.line = d3.line()
      .x((d) => {
        return this.xScale(d.x);
      })
      .y((d) => {
        return this.yScale(d.y);
      });

    let chartdata = this.svg.selectAll(".chartdata")
      .data(this.ds)
      .enter().append("g")
      .attr("class", "chartdata");

    chartdata.append("path")
      .attr("class", "line")
      .attr("d", (d) => {
        return this.line(d.values);
      })
      .style("fill", "none")
      .style("stroke-width", "2px")
      .style("stroke", (d) => {
        return this.zScale(d.name);
      });

    chartdata.append("text")
      .datum((d)=> {
        return {
          name: d.name, value: d.values[d.values.length - 1]
        };
      })
      .attr("transform", (d) => {
        return "translate(" +
          this.xScale(d.value.x) + "," + this.yScale(d.value.y) + ")";
      })
      .attr('class', 'lineLabel')
      .attr("x", 3)
      .attr("dy", "0.35em")
      .style("font", "14px open-sans")
      .text((d) => {
        return d.name;
      });

    // add the dots
    chartdata.selectAll(".circle")
      .data((d) => {
        return d.values;
      })
      .enter().append("circle")
      .attr("class", "circle")
      .attr("r", 4)
      .attr("cx", (d) => {
        return this.xScale(d.x);
      })
      .attr("cy", (d) => {
        return this.yScale(d.y);
      })
      .style("fill", (d) => { // Add the colours dynamically
        return this.zScale(d.name);
      });
  }

private zoomEventHandler() {
    let zoom = d3.zoom()
      .scaleExtent([1, 2])
      .translateExtent([[0, -100], this.width + 90, this.height + 100]).on("zoom", () => this.zoomed());

    this.svg.call(zoom);
  }

private zoomed() {
    d3.select('.x-axis').call(this.xAxis.scale(d3.event.transform.rescaleX(this.xScale)));
    d3.selectAll('.line').attr('transform', 'translate(' + d3.event.transform.x + ',' + d3.event.transform.y + ') scale(' + d3.event.transform.k + ')');
    d3.selectAll('.circle').attr('transform', 'translate(' + d3.event.transform.x + ',' + d3.event.transform.y + ') scale(' + d3.event.transform.k + ')');
}

我的图表正在响应鼠标滚动事件,如下所示。

The chart is not

有关我的代码错误的建议吗?

谢谢!

0 个答案:

没有答案