0

I have a Dimple.JS scatter plot with a time-based (in years) X-axis. I'd like (in a similar manner to this D3 question) to be able to shade in an arbitrary area (ideally the start and end positions wouldn't necessarily be data points in the series).

Is there an existing function that will let me supply a year and give me the X co-ordinate the correct position on the scale in the SVG, which I can then use the construct my rectangle (I tried to look at the source code to figure out how dimple does it's positioning...)?

Alternatively, if it's more practical to use points already plotted on the chart, what's the correct way to use d3.select with dimple to access a specific one? My series has a date field (dd/mm/yyyy) so I have SVG elements like this:

<circle id="All_Wed Mar 18 1931 00:00:00 GMT+0000 (GMT)__" class="series0 bubble All Wed_Mar_18_1931_00:00:00_GMT+0000_(GMT) " cx="465.0000000006503" cy="362.1714285714286" r="2" opacity="0.8" fill="#e90e0e" stroke="#c20b0b"></circle>

… my guess was I should use mySeries.shapes.select(id) to access that, but for:

mySeries.shapes.select("#All_Wed Mar 18 1931 00:00:00 GMT+0000 (GMT)__");

or (if I escape it, unless there's a silly syntax error):

mySeries.shapes.select("#All_Wed Mar\ 18\ 1931\ 00:00:00\ GMT+0000\ (GMT)__");

I get "Not a valid selector".

(Thanks)

Community
  • 1
  • 1
William Turrell
  • 3,227
  • 7
  • 39
  • 57

1 Answers1

1

You need to use a non-public method of the axes to do this, so it may not work this way in future versions (>1.1.5) however between you and me, I don't think the scale method of the axis is going to be disappearing any time soon.

The _scale method is the raw d3 scale method added once the draw method of the chart is called so it can convert the values for you. I've created a fiddle to illustrate the solution. This will need a little tweaking if you are dealing with negative values or log axes:

// Draw a simple chart
var svg = dimple.newSvg("body", 800, 600);
var data = [
    { "a":300, "b":2000, "c":"a" },
    { "a":400, "b":3000, "c":"b" },
    { "a":340, "b":2200, "c":"c" },
    { "a":300, "b":5000, "c":"d" }
];
var chart = new dimple.chart(svg, data);
var x = chart.addMeasureAxis("x", "a");
var y = chart.addMeasureAxis("y", "b");
chart.addSeries("c", dimple.plot.bubble);
chart.draw();

// Draw a grey region using the following co-ordinates
var fromX = x._scale(210),
    toX = x._scale(320),
    fromY = y._scale(2200),
    toY = y._scale(3100)

svg.append("rect")
    .attr("x", fromX)
    .attr("y", toY)
    .attr("width", toX - fromX)
    .attr("height", fromY - toY)
    .style("fill", "grey")
    .style("opacity", 0.2);

Here's the fiddle: http://jsfiddle.net/T6ZDL/7/

John Kiernander
  • 4,904
  • 1
  • 15
  • 29
  • That's great - thank you. I'll add for others that you need to use `new Date('1950-12-15')` when calling ._scale on a time axis. – William Turrell Apr 04 '14 at 10:12
  • 1
    Ah good point. Actually you might be better using d3 time parsing methods, `new Date()` has some cross-browser problems. Try using `d3.time.format("%Y-%m-%d").parse("1950-12-15")` instead to avoid ambiguity. – John Kiernander Apr 04 '14 at 10:18
  • One issue I spotted was z-index order (SVG z-index is determined only by order of insertion) – if the rectangle covers any data points, mouseover doesn't work. Fix based on [another question](http://stackoverflow.com/questions/14167863/how-can-i-bring-a-circle-to-the-front-with-d3): http://jsfiddle.net/T6ZDL/8/ – William Turrell Apr 04 '14 at 14:09
  • 1
    Cool, FYI, if you want to keep a shape in front but still have tool tips firing underneath you can add this to your rectangle: `.style("pointer-events", "none")`. It prevents the shape from catching events and passes them to shapes underneath. – John Kiernander Apr 04 '14 at 14:54