如何使用"d3.js"在折线图中放置圆(点)图书馆? [英] How to place Circles(dots) in line chart using "d3.js " library?

查看:196
本文介绍了如何使用"d3.js"在折线图中放置圆(点)图书馆?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用d3.js制作折线图,并在其中将圆圈放在数据位置.但是圆在折线图中放置在错误的位置.我该如何解决?

I want to make a line chart using d3.js in which I want to put circle at the data's position. But circle are placed in wrong position in line chart. How can I resolve this ?

我在Angular工作. 基本数据集看起来像

I am working in Angular. Basic data set looks like

{
          type: 'Advanced',
          wcpm: 40,
          date: '11-25-2019',
          comment: [
            'Lorem Ipsum Lorem Ipsum Lorem 1',
            'Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum 2'
          ]
 }

输出图像链接: https://ibb.co/pwRdXjx

第一个圆应放置在Jan25上,但位置错误.

in which first circle should be placed on Jan25 but it is placed at the wrong position.

class AppComponent implements OnInit {
 title = 'chart';
 margin = { top: 50, right: 50, bottom: 50, left: 50 };
 width = 1200 - this.margin.left - this.margin.right;
 height = 700 - this.margin.top - this.margin.bottom;
 svg: any;
 xScale: any;
 yScale: any;
 line: any;
 toolTipDiv: any;
ngOnInit() {

// XAXIS
this.xScale = d3.scaleBand()
  .domain(this.dataset[0].fluencyData.map((data) => {
    return new Date(data.date);
  }))
  .range([0, this.width]);

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

// Line Generator
this.line = d3.line()
  .x((d) => this.xScale(new Date(d.date)))
  .y((d) => this.yScale(d.wcpm));
// .curve(d3.curveMonotoneX);

// Add SVG to Div
this.svg = d3.select('#displayChart').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 + ')');

// Define the div for the tooltip
this.toolTipDiv = d3.select('#displayChart').append('div')
  .attr('class', 'tooltip')
  .style('opacity', 0);

// Append XAXIS to the SVG
this.svg.append('g')
  .attr('class', 'xAxis')
  .attr('transform', 'translate(0,' + this.height + ')')
  .call(d3.axisBottom(this.xScale).tickSizeOuter(0).tickFormat(d3.timeFormat('%b %d')));

// Append YAXIS to SVG
this.svg.append('g')
  .attr('class', 'yAxis')
  .call(d3.axisLeft(this.yScale).tickSize(-this.width)
  );

// Make a Path for Dataset
this.svg.append('path')
  .datum(this.dataset[0].fluencyData)
  .attr('class', 'line')
  .attr('d', this.line);

// 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');

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

appendCircles() {
  this.svg.selectAll('.developing')
  .data(this.dataset[0].fluencyData)
  .enter().append('circle')
  .attr('class', (d) => d.type)
  .attr('cx', (d) => this.xScale(new Date(d.date)))
  .attr('cy', (d) => this.yScale(d.wcpm))
  .attr('r', 5)
  .on('mouseover', (d) => {
    this.toolTipDiv.transition()
      .duration(200)
      .style('opacity', .9);
    this.toolTipDiv.html(d.wcpm + '<br/>' + d.type + '<br/>' + d.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);
  });
}
}

推荐答案

带比例尺期望每个数据项都用具有一定宽度的东西表示,例如条形图中的条形图.该元素的缩放空间(带)的宽度从xBandScale(value)xBandScale(value) + xBandScale.bandwidth().这很方便,因为它使您可以将矩形的x值设置为xBandScale(value),将宽度设置为xBandScale.bandwidth().

A band scale anticipates that each data item is represented with something having width, such as a bar in a bar chart. The width of the scaled space (the band) for that element is from xBandScale(value) through to xBandScale(value) + xBandScale.bandwidth(). This is handy in that it lets you set the x value of a rectangle to xBandScale(value) and the width to xBandScale.bandwidth().

但是,如果要定位圆,则希望它们位于此空间的中心.您正在使用xScale(value)定位点,这是该带的左侧:

But if you are positioning circles, you want them to be in the centered in the middle of this space. You are positioning your points with xScale(value), which is the left hand side of the band:

轴刻度线是偏移的,因为它们可以预测波段的宽度,毕竟我们正在将波段比例传递给轴生成器.

The axis ticks are offset because they anticipate the band's width, afterall we are passing a band scale to the axis generator.

是的,您可以使用以下方式定位圈子:

Yes, you could position your circles with:

.attr("cx", function(d) { return xScale(d.someProperty) + xScale.bandwidth()/2 })

这将把圆放置在带的中间-使圆与轴刻度对齐.但是,您的线将不会从垂直轴开始,即使这行得通,但这也不是频段标尺的预期目的.

This will place the circle in the middle of the band - which aligns your circles with your axis ticks. But, your line won't start at the vertical axis, and this isn't really the intended purpose of the band scale, even though it works.

相反,我们可以尝试d3.scalePoint-这也是一个序数标尺,类似于乐队标尺.文档指出:点标度通常用于按序或分类维的散点图."当您的对象没有宽度(或更准确地说,位于带的中间)时,它们是理想的选择.

Instead, we could try d3.scalePoint - which is also an ordinal scale and similar to a band scale. The docs state: "Point scales are typically used for scatterplots with an ordinal or categorical dimension." They are ideal where you have objects that don't have width (or more accurately, are positioned in the middle of the band).

有了这个,我们得到一个看起来像的图形(使用与上面相同的数据和结构):

With this we get a graph that looks like (using the same data and structure as above):

请注意,点之间的间距为xScale.step(),轴刻度已经移动(同样,最后一步超出了轴线-只是为了说明,轴在d处结束).

Note that the spacing between points is xScale.step(), the axis ticks have moved (also, the last step exceeds the axis line - it is just for illustration, the axis ends at d).

最后,如果我们有一个表示时间或其他连续量的坐标轴,则可以使用d3中的任何连续刻度,而不必使用序数刻度,这通常是更可取的.

Lastly, if we have an axis that represents something like time or some other contiuous quantity, we can use any of the continuous scales in d3 as well rather than an ordinal scale, which may often be preferable.

为简单起见,我假设没有填充以使图像更易于阅读

这篇关于如何使用"d3.js"在折线图中放置圆(点)图书馆?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆