user1529891
user1529891

Reputation:

d3 transform scale date to x position?

I have a linear y scale with a time series x scale. I want to put an overlay that follows the x/y value (similar to http://bl.ocks.org/mbostock/3902569).

The issue is that I'm not able to transform to the proper x scale value; for example when I mouseover my chart it outputs (this data is correct):

{ y: 0.05, x: "2015-07-26 15:08:47" }
{ y: 0.05, x: "2015-07-26 15:08:47" }
{ y: 0.05, x: "2015-07-26 15:08:47" }

Now I want to use this data to draw a point at that location; the issue is that I cannot replicate the above bl.locks.org example, and the transform isn't able to use the x position as a date; so how can I transform that x date to the point on the chart?

My mousemove is below:

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

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

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

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

var varea = d3.svg.area()
    .defined(function(d) { return d.y != null; })
    .x(function(d) { return x(parseDate(d.x)); })
    .y0(height)
    .y1(function(d) { return y(d.y); });

var svg = d3.select(".swatch").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 + ")");

x.domain(d3.extent(data, function(d) { return parseDate(d.x); }));
y.domain([0, d3.max(data, function(d) {
    if (d.y >= 1) {
        return d.y
    }

    return 1;
})]);

svg.append("path")
  .attr("class", "area")
  .attr("d", varea(data));

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

svg.append("g")
  .attr("class", "y axis")
  .call(yAxis);

var focus = svg.append("g")
    .attr("class", "focus")
    .attr("display", "none");

focus.append("circle")
    .attr("r", 4.5);

focus.append("text")
    .attr("x", 9)
    .attr("dy", ".35em");

svg.append("rect")
    .attr("class", "overlay")
    .attr("width", width)
    .attr("height", height)
    .on("mouseover", function() {
        focus.style("display", null);
    })
    .on("mouseout", function() {
        focus.style("display", "none");
    })
    .on("mousemove", function() {
        var x0 = x.invert(d3.mouse(this)[0]);

        var bisect = d3.bisector(function(d) { return parseDate(d.x); }).right;

        var item = data[bisect(data, x0)];

        focus.attr("transform", "translate(" + x(parseDate(item.x)) + "," + y(item.y) + ")");
        focus.select("text").text(item.y);

        console.log(x(parseDate(item.x)));
        console.log(y(item.y));
    });

This code produces errors like the following in the console:

Unexpected value translate(NaN,120) parsing transform attribute.

So, the question is how do I convert the date to a proper coordinate?

Upvotes: 0

Views: 1632

Answers (1)

user1529891
user1529891

Reputation:

Alright, so there were a couple of problems with my code.

I wasn't parsing the x value as a date; so I started parsing it with parseDate (see sample code) and then passed it to the x scale; this allowed me to get proper location on the chart.

The second issue was that display wasn't be set properly (setting it to null in Firefox wasn't allowing it to appear). So I changed that to display: inline; and it started showing up on the chart.

Upvotes: 1

Related Questions