charges.js 5.15 KB
var margin = {top: 60, right: 30, bottom: 130, left: 90},
    width = 1000 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

const tooltip_offset = {dx: 0, dy: 100}


// TODO: set main scales attr here then domain later
// const x = d3.scaleBand()
//     .range([0, width])
//     .padding(0.2);
//
// const y = d3.scaleLinear()
//     .range([height, 0]);
//

var color = d3.scaleOrdinal()
    .range([
        "#800000",
        "#FFFF00",
        "#808000",
        "#00FF00",
        "#008000",
        "#00FFFF",
        "#008080",
        "#0000FF",
        "#000080",
        "#FF00FF",
        "#800080",
    ]);

function build_chart(div_selector, data_url,  project_name, category) {

    if( category == 'capacity'){
        var chart_title = "Charges par fonction"
        var category_title = "Fonction"
    } else if ( category == 'service'){
        var chart_title = "Charges par service"
        var category_title = "Service"
    }

    const svg = d3.select(div_selector).append("svg")
        .attr("id", "svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    const tooltip = d3.select('html')
        .append("div")
        .style("opacity", 0)
        .attr("class", "tooltip")

    var mousemove = function (e, d) {
        tooltip
            .style("left", (e.pageX - tooltip_offset.dx) + "px")
            .style("top", (e.pageY - tooltip_offset.dy) + "px")
    }

    var mouseleave = function (d) {
        tooltip
            .transition()
            .duration(100)
            .style("opacity", 0)
    }

    var mouseover = function (e, d) {
        var category_name = d3.select(this.parentNode).datum().key
        var category_charge = d.data[category_name]
        tooltip
            .transition()
            .duration(200)
            .style("opacity", 1);
        tooltip
            .html("<b>"+category_title+":</b> " + category_name + "<br>" + "<b>Charge:</b> " + category_charge + "%")
            .style("left", (e.pageX - tooltip_offset.dx) + "px")
            .style("top", (e.pageY - tooltip_offset.dy) + "px")
    }

    d3.csv(data_url).then(data => {
        var services = data.columns.slice(1)
        var periods = d3.map(data, d => d.period)

        var stack = d3.stack()
            .keys(services)
        // .order(d3.stackOrderNone)
        // .offset(d3.stackOffsetNone);
        var stacked_data = stack(data)

        const x = d3.scaleBand()
            .domain(periods)
            .range([0, width])
            .padding(0.2);

        // Get the max y to plot
        y_max = d3.max(stacked_data[stacked_data.length - 1], d => d[1]);
        if (y_max == 0) {
            y_max = 100
        }
        // Enhance it by 20% to leave room on the top of the graph
        y_max = y_max * 1.1

        const y = d3.scaleLinear()
            .range([height, 0])
            .domain([0, y_max]);

        // Sur l'axe horizontal, on filtre les dates afficher
        const xAxis = d3.axisBottom(x)
        // .tickValues(x.domain().filter(d => (d.includes("06/0") || d.includes("21/0"))));

        const yAxis = d3.axisLeft(y)
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis)
            .selectAll("text")
            .style("text-anchor", "end")
            .attr("dx", "-.9em")
            .attr("dy", ".15em")
            .attr("transform", "rotate(-65)");

        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
        // .append("text")
        // .attr("fill", "#000")
        // .attr("transform", "rotate(-90)")
        // .attr("y", 6)
        // .attr("dy", "0.91em")
        // .style("text-anchor", "end")
        // .text("rate");

        svg.append("text")
            .attr("text-anchor", "end")
            .attr("transform", "rotate(-90)")
            .attr("y", -margin.left + 40)
            .attr("x", -margin.top - 70)
            .text("Charge (% ETP)")

        svg.append("text")
        .attr("x", (width / 2))
        .attr("y", 0 - (margin.top / 2)-10)
        .attr("text-anchor", "middle")
        .style("font-size", "16px")
        .text(project_name);


        svg.append("text")
        .attr("x", (width / 2))
        .attr("y", 0 - (margin.top / 2)+10)
        .attr("text-anchor", "middle")
        .style("font-size", "12px")
        .text(chart_title);

        let groups = svg.selectAll("g.category")
            .data(stacked_data)
            .enter()
            .append("g")
            .style("fill", (d) => color(d.key));

        let rect = groups.selectAll("rect")
            .data(d => d)
            .enter()
            .append("rect")
            .attr("class", "bar")
            .attr("x", d => x(d.data.period))
            .attr("width", x.bandwidth())
            // .attr("width", 5)
            .attr("y", d => y(d[1]))
            .attr("height", d => height - y(d[1] - d[0]))
            .on("mouseover", mouseover)
            .on("mousemove", mousemove)
            .on("mouseleave", mouseleave);

    });

}