This is pretty sophisticated stuff you're doing, so it's no wonder if it's a bit overwhelming. If you want to do this kind of deep customization, dc.js does not save you from learning d3.js (and there are those that would argue dc means you now have two things to learn).
When we did the regression line, that was separate data, because it was calculated from scratch. But here it's more convenient to with the existing dots and modify them. This way a lot less code is duplicated and you don't have to rewrite so much of what dc.js is doing.
So instead of an array of all the annotations, I'd keep a map of just the extra info about the annotations:
var annotateDots = {};
annotateDots[data[3].date.getTime()] = {"radius": 8, "color" : "green"};
annotateDots[data[7].date.getTime()] = {"radius": 8, "color" : "purple"};
annotateDots[data[0].date.getTime()] = {"radius": 8, "color" : "red"};
I'm using the date as the key into this object so that it will be easy to look up later. I have to use .getTime() in order to get the date object as an integer.
It's kind of tricky to get it working with transitions, so I've skipped that for now. Instead, I'll just remove any existing annotations at the end of the pretransition event, in line 126
chartBody.selectAll('circle.annotation').remove();
And I'll add a new renderlet which fires after transitions are done:
.on('renderlet', function(chart) {
var chartBody = chart.select('g.chart-body');
var circles = chartBody.selectAll("circle.dot"); // #1
circles.each(function(d, i) { // #2
var annotation = annotateDots[d.data.key.getTime()]; // #3
if(annotation) {
var that = this;
var dot = d3.select(this); // #4
dot
.attr('fill', annotation.color) // #5
.attr('opacity', 1);
d3.select(this.parentElement) // #6
.insert('circle', function() { return that; }) // #7
.attr({ // #8
class: 'annotation',
cx: dot.attr('cx'),
cy: dot.attr('cy'),
r: annotation.radius,
fill: 'none',
stroke: annotation.color
})
}
})
console.log('circles: ', circles);
handleDataPointClick();
});
1. select the existing dots (from the line chart, not ours)
2. loop over them
3. see if we have an annotation for the date of this dot
4. "this" is the element, make a d3 selection from this
5. change the color to what we want
6. select the parent so we can 7. add a sibling to the current dot, inserting directly before it
8. and set all the attributes for the outline circle at once.
It's all kind of busy, with a bit too much change and animation, but it sort of works:
Cheers,
Gordon