D3.js将圆添加到折线图上的每个其他点

时间:2020-09-20 03:40:14

标签: javascript d3.js

我有一个折线图,在A列和C列(而不是B列)的每个其他点上都需要有圆圈。我一直在努力寻找方法。这是我的不带圆圈的折线图:

enter image description here

date,A=count,A=rank,B=count,B=rank,C=count,C=rank
2016-11-01,60588,213,51915,46,41200,10
2016-12-01,73344,216,58536,47,41230,10
2017-01-01,64164,219,53203,50,51220,12
2017-02-01,85295,224,34047,52,61000,15
2017-03-01,86089,226,44636,54,71200,16
2017-04-01,96871,230,55281,55,71000,10
2017-05-01,97622,234,85879,55,67900,10

我尝试了数十种解决方案,但我感到非常困惑!这是我尝试过的事情之一:

linesAndDots.selectAll("line-circle")
    .data(data)
.enter().append("circle")
.attr("class", "data-circle")
.attr("r", 5)
.attr("cx", function(d) { return xScale(d.date); })
.attr("cy", function(d) { return yScale(d.measurement); });

但这会返还NaN的cx和cy值。

我的完整代码如下:

<!DOCTYPE html>
<meta charset="utf-8">
<head>
    <style>

path.line-0 {
    fill: none;
    stroke: #1F77B4;
}

path.line-1 {
    fill: none;
    stroke: #FF7F0E;
}

    </style>
</head>
<!-- Body tag is where we will append our SVG and SVG objects-->
<body>
</body>

<!-- Load in the d3 library -->
<script src="lib/d3.v5.min.js"></script>
<div id="svgdiv"></div>
<script>
//------------------------1. PREPARATION------------------------//
//-----------------------------SVG------------------------------//

var columns=['A=count','B=count'];
var columnsB=['A=rank','B=rank'];

var width = 960;
var height = 500;
var margin = 5;
var padding = 5;
var adj = 75;
// we are appending SVG first
var svg = d3.select("body").append("svg")
    .attr("preserveAspectRatio", "xMinYMin meet")
    .attr("viewBox", "-"
          + adj + " -"
          + adj + " "
          + (width + adj *3) + " "
          + (height + adj*3))
    .style("padding", padding)
    .style("margin", margin)
    .classed("svg-content", true);

//-----------------------------DATA-----------------------------//
var timeConv = d3.timeParse("%Y-%m-%d");
var formatTime = d3.timeFormat("%b %y")
var dataset = d3.csv("toShare.csv");
dataset.then(function(data) {
    console.log(data.columns.slice(1))
    var slices = columns.map(function(id) {
        return {
            id: id,
            values: data.map(function(d){
                return {
                    date: timeConv(d.date),
                    measurement: +d[id]
                };
            })
        };
    })

//----------------------------SCALES----------------------------//
var xScale = d3.scaleTime().range([0,width]);
var yScale = d3.scaleLinear().rangeRound([height, 0]);
xScale.domain(d3.extent(data, function(d){
    return timeConv(d.date)}));
yScale.domain([(0), d3.max(slices, function(c) {
    return d3.max(c.values, function(d) {
        return d.measurement + 4; });
        })
    ]);

//-----------------------------AXES-----------------------------//
var yaxis = d3.axisLeft()
    .ticks(9)
    .scale(yScale);

var xaxis = d3.axisBottom()
    .ticks(7)
    .scale(xScale);

//----------------------------LINES-----------------------------//
var line = d3.line()
    .x(function(d) { return xScale(d.date); })
    .y(function(d) { return yScale(d.measurement); });

let id = 0;
var ids = function () {
    return "line-"+id++;
}
//-------------------------2. DRAWING---------------------------//
//-----------------------------AXES-----------------------------//

svg.append("g")
        .attr("class", "axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xaxis)
        .append("text")
          .attr("transform",
                "translate(" + (width/2) + " ," +
                               50 + ")")
          .style("text-anchor", "middle")
          .text("Month");

    svg.append("g")
        .attr("class", "axis")
        .call(yaxis)
        .append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 0 - adj)
          .attr("x",0 - (height / 2))
          .attr("dy", "1em")
          .style("text-anchor", "middle")
          .text("Running Total");
//----------------------------LINES-----------------------------//
var linesAndDots = svg.selectAll("lines")
    .data(slices)
    .enter()
    .append("g");

    linesAndDots.append("path")
    .attr("class", ids)
    .attr("d", function(d) { return line(d.values); });

    linesAndDots.selectAll("line-circle")
        .data(data)
    .enter().append("circle")
    .attr("class", "data-circle")
    .attr("r", 5)
    .attr("cx", function(d) {
        console.log("id",  id)
        return 5; })
    .attr("cy", function(d) { return 40; });

    //Add the label on the right
    linesAndDots.append("text")
    .attr("class", ids)
    .datum(function(d) {
        return {
            id: d.id,
            value: d.values[d.values.length - 1]}; })
    .attr("transform", function(d) {
            return "translate(" + (xScale(d.value.date) + 10)
            + "," + (yScale(d.value.measurement) + 5 ) + ")"; })
    .attr("x", 5)
    .text(function(d) { return d.id.replace("=count", ""); });
});
</script>
</body>

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

可以通过查看showDetailsd函数中cx的真正含义来检查问题。
cy的问题:您没有像对切片数据那样将日期字符串解析为Date对象; cx的问题:数据项没有测量键。

您同时使用了cydata。为了使代码更一致,我也使用slices修复了圆图的代码。

slices

A demo here