Q: Set opacity of circles based on the occurrences in the parent element (Group) - D3.js I've been working on one internal project which is bubble chart displaying based on the year and the number of incidents, etc. I could display the bubbles but, we also have the TRACE functionality (checkbox) which would display the circles for the different years - circles overlapping each other if the TRACE checckbox is ticked. This is similar to slider range functionality. i.e. displaying the data based on the the date range, etc. The problem here is we would like to generate all the circles which has the same css class names with the different opacity. So, I guess we would need to find the different css class names dynamically in the selection / container and then apply the opacity (dynamically) so that the top circle (last generated based on the date range can have full opacity and the first circle( generated based on the first year) has been displayed at the last as z-index but, also has less opacity. Can you please help writing the appropriate function for the same?
1) Below code has been added when TRACE functionality is ON.
plotPoints = plotPointsHolder.selectAll('circle').data(stats.filter((d) => d.year <= year));
2) Below code will get executed if TRACE functionality is OFF.
plotPoints = plotPointsHolder.selectAll('circle').data(stats.filter((d) => d.year === year));
See below function for more information.
const renderStats = (stats, year) => {
        if (tracemode) {
            plotPoints = plotPointsHolder.selectAll('circle').data(stats.filter((d) => d.year <= year));
        } else {
            plotPoints = plotPointsHolder.selectAll('circle').data(stats.filter((d) => d.year === year));
        }
        plotPoints.exit()
            .remove();

        plotPoints.enter()
            .append('circle')
            .style('stroke', 'black')
            .style('stroke-width', '1')
            .style('fill', d => `${d.colour}`)
            .attr('class', d => `${d.type}`)
            .on('mouseover', function() {
                renderInfoMarker(this, "Circle", this.style.fill);
            })
            .on('mouseout', function() {
                removeRenderMarker(this, "Circle");
            })
            .merge(plotPoints)
            //.transition()
            //.duration(100)
            .attr('cx', function(d) { return x(d.survival); })
            .attr('cy', function(d) { return y(d.death); })
            .attr('r', function(d) {

                return map_bubble_size(d.incidence, radiusVal.min_radius, radiusVal.max_radius, radiusVal.min_value, radiusVal.max_value, radiusVal.beta);

                //return radius(d.incidence);
            });
    }


A: 
The problem here is we would like to generate all the circles which has the same css class names with the different opacity. 

Map the date data to a scale and apply a function to the fill-opacity attribute that returns a value between 0 and 1.
var dates = stats.map( function(d) { return d.year }); //map date data

var opacity = d3.scaleSqrt().domain([Math.min(...dates),Math.max(...dates)]).range([0.1, 0.9]); //scale map data with square root scale

plotPoints.enter()
        .append('circle')
        .style('stroke', 'black')
        .style('stroke-width', '1')
        .style('fill', d => `${d.colour}`)
        .attr('fill-opacity', function(d) { return opacity(d.year);})
        .attr('class', d => `${d.type}`)
        .on('mouseover', function() {
            renderInfoMarker(this, "Circle", this.style.fill);
        })
        .on('mouseout', function() {
            removeRenderMarker(this, "Circle");
        })
        .merge(plotPoints)
        //.transition()
        //.duration(100)
        .attr('cx', function(d) { return x(d.survival); })
        .attr('cy', function(d) { return y(d.death); })
        .attr('r', function(d) {

            return map_bubble_size(d.incidence, radiusVal.min_radius, radiusVal.max_radius, radiusVal.min_value, radiusVal.max_value, radiusVal.beta);

            //return radius(d.incidence);
        });


A: I think @AF7TI is on the right track with your opacity problem, so I will answer the second part of this question.
Because svg doesn't have a "z-index" concept, the order of the elements matters. Luckily, d3 allows you to sort a selection , such that larger bubbles are drawn first (and you can mouseover the smaller ones). So something along these lines should work (this is pseudocode):
.merge(plotPoints).sort((a,b) => { map_bubble_size(a stuff) - map_bubble_size(b stuff)})

