使用d3 v5在折线图中的x轴上仅显示有限数量的日期

时间:2019-04-01 06:50:22

标签: d3.js charts

我已经使用d3版本5制作了折线图。我现在面临的问题是,如果我有10条记录,那么如果我有30条记录,它将在折线图中的x轴上显示所有记录的日期。记录,然后它将在x轴上显示所有30条记录的日期。但是我想做的是,最初它应该只显示7个记录的日期,而当我们平移时,应该可以看到另一个日期。我也已经在其中实现了平移。我如何才能使这件事最初加载少量记录,然后在平移时显示更多记录?我已经在角度2做到了。

  margin = { top: 50, right: 50, bottom: 50, left: 50 };
  svg: any;
  xScale: any;
  xScaleCopy: any;
  yScale: any;
  xAxis: any;
  yAxis: any;
  line: any;
  width: number;
  height: number;
  toolTipDiv: any;
  timeParse: any;
  ngOnInit() {
this.createLineChart();
  }

   private createLineChart() {
// Take date of format '01-25-2019'
this.timeParse = d3.timeParse('%m-%d-%Y');
this.width = (18 * 75) - this.margin.left - this.margin.right;
this.height = 600 - this.margin.top - this.margin.bottom;

// X AXIS
this.xScale = d3.scalePoint()
  .domain(this.dataset[0].fluencyData.map((data) => {
    return this.timeParse(data.date);
  }).sort((a, b) => {
    return a - b;  // As We have dates, you still need to order your entries.
  }))
  .range([0, this.width]);
this.xScaleCopy = this.xScale.copy();

// Y AXIS
this.yScale = d3.scaleLinear()
  .domain([0, 110])
  .range([this.height, 0]);

this.xAxis = d3.axisBottom().scale(this.xScale).tickSizeOuter(0).tickFormat(d3.timeFormat('%b %d'));
this.yAxis = d3.axisLeft().scale(this.yScale).tickSize(-(this.width + (this.margin.left + this.margin.right) / 2 + 20));

// Line Generator
this.line = d3.line()
  .x((data) => this.xScale(this.timeParse(data.date)))
  .y((data) => this.yScale(data.wcpm));

const zoom = d3.zoom()
  .scaleExtent([1, 30])  // This control how much you can unzoom and zoom
  // .translateExtent([[0, -Infinity], [2 * this.width, Infinity]])
  .extent([[0, 0], [this.width, this.height]])
  .translateExtent([[0, 0], [this.width, this.height]])
  .on('zoom', () => {
    this.xAxis.scale(this.xScale);
    groupX.call(this.xAxis);
    // Rescale X Axis
    this.xScale.range(this.xScaleCopy.range().map((d) => {
      return d3.event.transform.applyX(d);
    }));

    // Redraw the line:
    path.attr('d', this.line);

    // Redraw the circles:
    this.svg.selectAll('circle')
      .attr('cx', (data) => {
        return this.xScale(this.timeParse(data.date));
      });
  });

// Add SVG to Div
this.svg = d3.select('#displayChart').append('svg')
  // .attr('preserveAspectRatio', 'xMidYMid meet')
  // .attr(
  //   'viewBox',
  //   '0 0 ' +
  //   (this.width + this.margin.left + this.margin.right) +
  //   ' ' +
  //   (this.height + this.margin.top + this.margin.bottom))
  .attr('width', this.width + this.margin.left + this.margin.right + 20)
  .attr('height', this.height + this.margin.top + this.margin.bottom)
  .call(zoom)
  .append('g')
  .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');

// Set up a clip path for the circles and the path - so when we zoom we don't have overflow:
const clipPath = this.svg.append('clipPath')
  .attr('id', 'clip')
  .append('rect')
  .attr('x', -(this.margin.left + this.margin.right) / 2)
  .attr('y', -((this.margin.left + this.margin.right) / 2))
  .attr('width', this.width + (this.margin.left + this.margin.right) / 2 + 20)
  .attr('height', this.height + (this.margin.left + this.margin.right) / 2)
  .attr('fill', 'none')
  .style('pointer-events', 'none'); // we don't want mouse interaction.


// Append YAXIS to SVG
const groupY = this.svg.append('g')
  .attr('class', 'yAxis')
  .call(this.yAxis);

// Append XAXIS to the SVG
const groupX = this.svg.append('g')
  .attr('class', 'xAxis')
  .attr('transform', 'translate(' + ((this.margin.left + this.margin.right) / 2) + ',' + (this.height) + ')')
  // .attr('transform', 'translate(0,' + this.height + ')')
  .call(this.xAxis)
  .attr('clip-path', 'url(#clip)');

// Make a Path for Dataset
const path = this.svg.append('path')
  .datum(this.dataset[0].fluencyData)
  .attr('class', 'line')
  .attr('d', this.line)
  .attr('transform', 'translate(' + ((this.margin.left + this.margin.right) / 2) + ',0 )')
  .attr('clip-path', 'url(#clip)'); // apply the clip path.;

// Append Circles in chart with different Colors
this.appendCircles();
this.setToolTips();

// Text Heading of DATE in chart
this.svg.append('text')
  .attr('transform', 'translate(' + (-20) + ',' + (this.height + 13) + ')')
  .attr('dy', '.35em')
  .attr('class', ' xAxis')
  .text('Date');
   }

    private setToolTips() {
// Define the div for the tooltip
this.toolTipDiv = d3.select('#displayChart').append('div')
  .attr('class', 'tooltip')
  .style('opacity', 0);
this.svg.selectAll('circle').on('mouseover', (data) => {
  this.toolTipDiv.transition()
    .duration(200).ease(d3.easeSinInOut)
    .style('opacity', .9);
  this.toolTipDiv.html(data.wcpm + '<br/>' + data.type + '<br/>' + data.date)
    .style('left', (d3.event.pageX - 50) + 'px')
    .style('top', (d3.event.pageY - 50) + 'px');
})
  .on('mouseout', () => {
    this.toolTipDiv.transition()
      .duration(500)
      .style('opacity', 0);
  });
   }

    private appendCircles() {
this.svg.selectAll('.developing')
  .data(this.dataset[0].fluencyData)
  .enter().append('circle')
  .attr('class', (data) => data.type)
  .attr('cx', (data) => {
    return this.xScale(this.timeParse(data.date));
  })
  .attr('cy', (data) => this.yScale(data.wcpm))
  .attr('r', 5)
  .attr('transform', 'translate(' + ((this.margin.left + this.margin.right) / 2) + ',0)')
  .attr('clip-path', 'url(#clip)'); // apply the clip path.
   }

  ngOnDestroy() {
d3.select('svg').remove();
   }

0 个答案:

没有答案