3gwebtrain
3gwebtrain

Reputation: 15293

d3js - line chart adding `circles` throw errors

My goal is making a multiple line of line drawing. It is all working fine other than adding the circles on the curves.

Below is the code snippets. HTML and CSS also added below. Can anyone please help me to fix this?

window.onload = function () {
  
var datas = [
{"date":20111001,"New York" : 63.4, "San Franscisco" : 62.7, "Austin" : 72.2 },
{"date":20111002,"New York" : 58.0, "San Franscisco" : 59.9, "Austin" : 67.7 },
{"date":20111003,"New York" : 53.3, "San Franscisco" : 59.1, "Austin" : 69.4 },
{"date":20111004,"New York" : 55.7, "San Franscisco" : 58.8, "Austin" : 68.0 },
{"date":20111005,"New York" : 64.2, "San Franscisco" : 58.7, "Austin" : 72.4 },
{"date":20111006,"New York" : 58.8, "San Franscisco" : 57.0, "Austin" : 77.0 },
{"date":20111007,"New York" : 57.9, "San Franscisco" : 56.7, "Austin" : 82.3 },
{"date":20111008,"New York" : 61.8, "San Franscisco" : 56.8, "Austin" : 78.9 },
{"date":20111009,"New York" : 69.3, "San Franscisco" : 56.7, "Austin" : 68.8 },
{"date":20111010,"New York" : 71.2, "San Franscisco" : 60.1, "Austin" : 68.7 }

]

var margin = {top: 20, right: 80, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var parseDate = d3.time.format("%Y%m%d").parse;

var x = d3.time.scale().range([0, width]);

var y = d3.scale.linear().range([height, 0]);

var color = d3.scale.ordinal()
      .domain(["New York", "San Francisco", "Austin"])
      .range(["#FF0000", "#009933" , "#0000FF"]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.temperature); });

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


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

  datas.forEach(function(d) {
    d.date = parseDate(d.date + "");
  });

  var cities = color.domain().map(function(name) {
    return {
      name: name,
      values: datas.map(function(d) {
        return {date: d.date, temperature: +d[name]};
      })
    };
  });
  

  x.domain(d3.extent(datas, function(d) { return d.date; }));

  y.domain([
    d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }),
    d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); })
  ]);

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

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    // .append("text")
    //   .attr("transform", "rotate(-90)")
    //   .attr("y", 6)
    //   .attr("dy", ".71em")
    //   .style("text-anchor", "end")
    //   .text("Temperature (ºF)");

  var city = svg.selectAll(".city")
      .data(cities)
      .enter().append("g")
      .attr("class", "city");

  var path = city.append("path")
      .attr("class", "line")
      .attr("d", function(d) { return line(d.values); })
      .style("stroke", function(d) { return color(d.name); });
      
  var totalLength = [path[0][0].getTotalLength()];
  
  path
      .attr("stroke-dasharray", totalLength + " " + totalLength)
      .attr("stroke-dashoffset", totalLength)
      .transition()
      .duration(2000)
      .ease("linear")
      .attr("stroke-dashoffset", 0);
      
  city.selectAll("circle.line")
		    .data(cities)
		    .enter().append("svg:circle")
		    .attr("class", "line")
		    .attr("stroke-width", 2)
        .attr("stroke", "green")
        .attr("fill", "transparent")
		    .attr("cx", function(d,i){ return line(d.values) })
		    .attr("cy", function(d,i){ return line(d.values) })
		    .attr("r", 3.5);

  // city.append("text")
  //     .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
  //     .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")"; })
  //     .attr("x", 3)
  //     .attr("dy", ".35em")
  //     .text(function(d) { return d.name; });

}
body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.x.axis path {
  display: none;
}

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Upvotes: 0

Views: 137

Answers (1)

Gilsha
Gilsha

Reputation: 14591

Try this way.

  city.selectAll("circle")
    .data(function(d) {
      return d.values
    })
    .enter()
    .append("circle")
    .attr("r", 3.5)
    .attr("cx", function(d) {
      return x(d.date)
    })
    .attr("cy", function(d) {
      return y(d.temperature)
    })
    .attr("stroke-width", 2)
    .attr("stroke", "green")
    .attr("fill", "transparent");

Note: I have commented the line interpolation, since it is not possible to find the exact point positions in that case. Reference: points on line in d3.js

window.onload = function() {

  var datas = [{
      "date": 20111001,
      "New York": 63.4,
      "San Franscisco": 62.7,
      "Austin": 72.2
    }, {
      "date": 20111002,
      "New York": 58.0,
      "San Franscisco": 59.9,
      "Austin": 67.7
    }, {
      "date": 20111003,
      "New York": 53.3,
      "San Franscisco": 59.1,
      "Austin": 69.4
    }, {
      "date": 20111004,
      "New York": 55.7,
      "San Franscisco": 58.8,
      "Austin": 68.0
    }, {
      "date": 20111005,
      "New York": 64.2,
      "San Franscisco": 58.7,
      "Austin": 72.4
    }, {
      "date": 20111006,
      "New York": 58.8,
      "San Franscisco": 57.0,
      "Austin": 77.0
    }, {
      "date": 20111007,
      "New York": 57.9,
      "San Franscisco": 56.7,
      "Austin": 82.3
    }, {
      "date": 20111008,
      "New York": 61.8,
      "San Franscisco": 56.8,
      "Austin": 78.9
    }, {
      "date": 20111009,
      "New York": 69.3,
      "San Franscisco": 56.7,
      "Austin": 68.8
    }, {
      "date": 20111010,
      "New York": 71.2,
      "San Franscisco": 60.1,
      "Austin": 68.7
    }

  ]

  var margin = {
      top: 20,
      right: 80,
      bottom: 30,
      left: 50
    },
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

  var parseDate = d3.time.format("%Y%m%d").parse;

  var x = d3.time.scale().range([0, width]);

  var y = d3.scale.linear().range([height, 0]);

  var color = d3.scale.ordinal()
    .domain(["New York", "San Francisco", "Austin"])
    .range(["#FF0000", "#009933", "#0000FF"]);

  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

  var line = d3.svg.line()
    //  .interpolate("basis")
    .x(function(d) {
      return x(d.date);
    })
    .y(function(d) {
      return y(d.temperature);
    });

  var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


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

  datas.forEach(function(d) {
    d.date = parseDate(d.date + "");
  });

  var cities = color.domain().map(function(name) {
    return {
      name: name,
      values: datas.map(function(d) {
        return {
          date: d.date,
          temperature: +d[name]
        };
      })
    };
  });


  x.domain(d3.extent(datas, function(d) {
    return d.date;
  }));

  y.domain([
    d3.min(cities, function(c) {
      return d3.min(c.values, function(v) {
        return v.temperature;
      });
    }),
    d3.max(cities, function(c) {
      return d3.max(c.values, function(v) {
        return v.temperature;
      });
    })
  ]);

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

  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    // .append("text")
    //   .attr("transform", "rotate(-90)")
    //   .attr("y", 6)
    //   .attr("dy", ".71em")
    //   .style("text-anchor", "end")
    //   .text("Temperature (ºF)");

  var city = svg.selectAll(".city")
    .data(cities)
    .enter().append("g")
    .attr("class", "city");

  var path = city.append("path")
    .attr("class", "line")
    .attr("d", function(d) {
      return line(d.values);
    })
    .style("stroke", function(d) {
      return color(d.name);
    });

  var totalLength = [path[0][0].getTotalLength()];

  path
    .attr("stroke-dasharray", totalLength + " " + totalLength)
    .attr("stroke-dashoffset", totalLength)
    .transition()
    .duration(2000)
    .ease("linear")
    .attr("stroke-dashoffset", 0);

  city.selectAll("circle")
    .data(function(d) {
      return d.values
    })
    .enter()
    .append("circle")
    .attr("r", 3.5)
    .attr("cx", function(d) {
      return x(d.date)
    })
    .attr("cy", function(d) {
      return y(d.temperature)
    })
    .attr("r", 3.5)
    .attr("fill", "transparent")
    .attr("stroke", "green")
    .attr("stroke-width", 0)
    .transition()
    .duration(2000)
    .attr("stroke-width", 2)

  // city.append("text")
  //     .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
  //     .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")"; })
  //     .attr("x", 3)
  //     .attr("dy", ".35em")
  //     .text(function(d) { return d.name; });

}
body {
  font: 10px sans-serif;
}
.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
.x.axis path {
  display: none;
}
.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Upvotes: 1

Related Questions