D3 scatterplot using time scale on x-axis — not wo

2019-07-08 06:09发布

问题:

I've created a pretty simple scatterplot showing a person's weightlifting progress over time. The x-axis is a time scale in days (there's one circle for each day) and the y-axis is the number of pounds lifted that day.

The scatterplot works in Chrome, but not Firefox. It has something to do with using a date object as the x-position of the circles.

Take a look at the chart in Chrome

Here are two rows of my dataset, to show how it is formatted (the date is the first item of each row):

    ["2011-09-16",150,"Cottage cheese and 1 apple",170,16,"4 Chicken breast strips",130,17,"Hibachi grill: onion soup, salad, 2 shrimp pieces, vegetables. 12 oz chicken, rice",880,99,"Small hard frozen yogurt",300,6,"Cottage cheese, greek yogurt, a bunch of icebreaker sours",230,26,1710,164,175,"Back/biceps, 31 pushups",135,0,0],
    ["2011-09-17",150,"15 peanuts",80,4,"Dim Sum",1000,40,"Azn salad, 2 serv chicken breast",490,57,"8.8 oz mixx",264,9,"(No Data)",0,0,1833.6875,109.55,174.2," ",135,0,0],

Here's how I draw the circles, and some relevant functions/variables I used to format the dates:

    //Width and height
    var w = 4200;
    var h = 200;
    var padding = 35;

    var mindate = new Date("2011-9-15");
    var maxdate = new Date("2012-5-29");

    //Create scale functions
    var xScale = d3.time.scale()
                        .domain([mindate, maxdate])
                        .range([padding, w - padding * 2]);

    var format = d3.time.format("%Y-%m-%d");
    var dateFn = function(d) {return format.parse(d[0])};

    //Create circles
        svg.selectAll("circle")
           .data(dataset)
           .enter()
           .append("circle")
           .attr("cx", function(d) {
                return xScale(dateFn(d));
           })
           .attr("cy", function(d) {
                return yScale(d[1]);
           })
           .attr("r", 6)
           .attr("fill", "gray")
           .attr("opacity", .5)

Like I said, it works exactly how I want in Chrome, but in Firefox, all the circles are on top of one another with cx=0. Any ideas would be appreciated. I asked my local d3 expert, and he showed me a project he did which also fails in Firefox due to drawing circles using date objects. He just gave up. a link to his project

回答1:

The problem isn't the way you're parsing the dates, but the way you're setting up the scale.

var mindate = new Date("2011-9-15");
var maxdate = new Date("2012-5-29");

This is the code that works properly only in Chrome because you're relying on its date parsing by using the constructor rather than parsing explicitly like you're doing for the rest of the dates.

The fix is simple -- just parse the dates you're using to set the scale domain as well:

var format = d3.time.format("%Y-%m-%d"),
    mindate = format.parse("2011-09-15"),
    maxdate = format.parse("2012-05-29");