Redraw d3 pie chart on click

I have two d3 chart one pie and one bar. I would like to redraw the pie chart when the bar is clicked. The pie chart should take the key of te bar chart element selected.

I succeed to create a new pie chart each time a click append but I do not understand how I am suppose to implement to the onclick function to redraw the pie instead of creates a new one.

main.js

/*
    MAIN CONTROLLER

    - Instantiates data manager, and makes it load data
    - Gives dashboard DOM structure
    - Generates bar charts in dashboard
    - Feeds data from data manager into bar charts
    - Provides bar charts click interaction

    Author: Pierre Le Bras
    Date Created: 31/10/17

*/


var dataManager = {};

function startApplication(){

    dataManager = dataManager();

    dataManager.loadCsv("csvFiles/REF2014_Results.csv",
        function(error){ // to call in case of error
            console.log("Error");
            console.log(error);
        },
        function(){ // to call if everything ok
            makePage();
        });
}

function makePage(){
    var dash = d3.select('div#dashboard');

    // EDIT PAGE STRUCTURE
    dash.append('div')
        .attr('id', 'bar1') // for renderer generation
        .classed("barchart", true) // for styling
            .append("h3").text("Number of submission per Univsersity");


    // APPEND VISUALISATION
    var bar1 = barchart("div#bar1")
        .setHeight(200)
        .setWidth(800)
        .setColor("#2b38c5")
        .setTooltipText(function(d, i){
            return "<b>"+d.key+"</b>: "+(d.value);
        })
        .loadAndRender(dataManager.getByName());

        bar1.setMouseclickCallback(function (d,i) {
            redraw();
        })

    // Piechart
    dash.append('div').attr('id','pie1').classed('piechart',true).append("h3").text("Number of submission by categories");
    var t = ["Anglia Ruskin University"];
    var s = ["Aston University"];
    var pie1 = piechart("div#pie1")
        .setHeight(960)
        .setWidth(500)
        .setRadius(960, 500)
        .setTooltipText(function (d, i) {
            return "<b>" + d.data.key + "</b>: " + (d.value);
        })
        .loadAndRender(dataManager.getArea(t))



    function redraw(){
        // just feed data to bars, dataManager will handle filters
        bar1.loadAndRender(dataManager.getByName());
        pie1.loadAndRender(dataManager.getArea());
    }
}

pie.js

function piechart(DOMElement){

    var pieObj = {}; // main object

    // ---- PUBLIC API

    // Sizing variables setters
    // parameters:
    //      - value
    // returns:
    //      - pieObj for chaining
    pieObj.setWidth = function(w){
        width = w;
        render();
        return pieObj;
    }
    pieObj.setHeight = function(h){
        height = h;
        render();
        return pieObj;
    }
    pieObj.setRadius = function(h,w){
        radius = Math.min(w,h)/2 ;
        render();
        return pieObj;
    }

    pieObj.setTooltipText = function(f){
        tooltipText = f;
        updateInteractions();
        return pieObj;
    }
    pieObj.setMouseoverCallback = function(f){
        mouseoverCallback = f;
        updateInteractions();
        return pieObj;
    }
    pieObj.setMouseoutCallback = function(f){
        mouseoutCallback = f;
        updateInteractions();
        return pieObj;
    }
    pieObj.setMouseclickCallback = function(f){
        mouseclickCallback = f;
        updateInteractions();
        return pieObj;
    }



    pieObj.loadAndRender = function(data,to_array){
        if  (to_array = true) {
            var arr = [];
            for (var key in data) {
                if (data.hasOwnProperty(key)) {
                    arr.push({
                        key: key,
                        value: data[key]
                    });
                }
            }
         dataset = arr;
        }
        console.log('lol',dataset);
        render();
        return pieObj;
    }

    // ---- PRIVATE VARIABLES

    // dom elements
    var svg = d3.select(DOMElement).append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("pies")
        .attr("transform", "translate(" + radius + "," + radius + ")");



    var tooltip = d3.select(DOMElement).append("div")
        .classed("tooltip", true);

    // scales
    var xScale = d3.scaleBand(),
        yScale = d3.scaleLinear();


    var width = 960,
        height = 500,
        radius = Math.min(width, height) / 2;

    var color = d3.scaleOrdinal()
        .range(["#2b1dc5", "#3f1da6", "#531988"]);

    var arc = d3.arc()
        .outerRadius(radius - 10)
        .innerRadius(0);

    var labelArc = d3.arc()
        .outerRadius(radius - 40)
        .innerRadius(radius - 40);

    var pie = d3.pie()
        .sort(null)
        .value(function(d) { return d.value; });

    var svg = d3.select(DOMElement).append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    // data
    var dataset =[];

    // interaction settings
    var tooltipText = function(d, i){return "tooltip over element "+i;}
    var mouseoverCallback = function(d, i){ };
    var mouseoutCallback = function(d, i){ };
    var mouseclickCallback = function(d, i){ console.log(d, i) };
    var keySelected = null;

    // ---- PRIVATE FUNCTIONS

    function render(){

        GUP_pies();
        updateStyles();
        updateInteractions();
    }

    function GUP_pies(){

        var increments = 300;
        var t1 = d3.transition().duration(increments),
            t2 = d3.transition().delay(increments).duration(increments),
            t3 = d3.transition().delay(increments*2).duration(increments),
            t4 = d3.transition().delay(increments*3).duration(increments);

        var g = svg.selectAll(".arc")
            .data(pie(dataset))
            .enter().append("g")
            .attr("class", "arc");

        g.append("path")
            .attr("d", arc)
            .transition(t4)
            .style("fill", function(d) { return color(d.value); });

        g.append("text")
            .attr("transform", function(d) { return "translate(" + labelArc.centroid(d) + ")"; })
            .attr("dy", ".35em")
            .text(function(d) { return d.value; });



        g.transition(t2)
            .attr("class",arc);

    }

    function updateStyles(){
        // separate function for styles,
        // this way there is no need to do GUP when just changing colour
        svg.selectAll(".arc")
            .style("fill", color)
            .style("stroke", "#424242")
            .style("opacity", 1.0)
    }

    function updateInteractions(){
        // separate function for interactions,
        // this way there is no need to do GUP when just changing callbacks
        svg.selectAll(".arc")
            .on("mouseover", function(d, i){
                d3.select(this).style("opacity", 0.7);

                tooltip.html(tooltipText(d,i))
                    .style("left", (d3.event.pageX) + "px")     
                    .style("top", (d3.event.pageY - 28) + "px")
                    .style("opacity", 0.9);

                mouseoverCallback(d, i);
            })
            .on("mouseout", function(d, i){
                d3.select(this).style("opacity", 1.0);

                tooltip.style("opacity", 0);

                mouseoutCallback(d, i);


            })

    }


    return pieObj; // returning the main object
}

bar.js

function barchart(DOMElement){

    var barObj = {}; // main object

    // ---- PUBLIC API

    // Sizing variables setters
    // parameters:
    //      - value
    // returns:
    //      - barObj for chaining
    barObj.setWidth = function(w){
        svgWidth = w;
        render();
        return barObj;
    }
    barObj.setHeight = function(h){
        svgHeight = h;
        render();
        return barObj;
    }
    barObj.setPadding = function(p){
        svgPadding = p;
        render();
        return barObj;
    }

    // Styling variables setters
    // parameters:
    //      - value
    // returns:
    //      - barObj for chaining
    barObj.setColor = function(c){
        barColor = c;
        updateStyles();
        return barObj;
    }

    // Callbacks setters
    // parameters:
    //      - callback
    // returns:
    //      - barObj for chaining
    barObj.setTooltipText = function(f){
        tooltipText = f;
        updateInteractions();
        return barObj;
    }
    barObj.setMouseoverCallback = function(f){
        mouseoverCallback = f;
        updateInteractions();
        return barObj;
    }
    barObj.setMouseoutCallback = function(f){
        mouseoutCallback = f;
        updateInteractions();
        return barObj;
    }
    barObj.setMouseclickCallback = function(f){
        mouseclickCallback = f;
        updateInteractions();
        return barObj;
    }


    // function loading data and rendering it in bar chart
    // parameters:
    //      - dataset in following format:
    //          [{"key": year, "value": money}, {...}, ...]
    // returns:
    //      - barObj for chaining
    barObj.loadAndRender = function(data){
        dataset = data;
        render();
        return barObj;
    }

    // ---- PRIVATE VARIABLES

    // sizing vars
    var svgWidth = 800,
        svgHeight = 600,
        svgPadding = 20;

    // styling vars
    var barColor = "#009688";

    // dom elements
    var svg = d3.select(DOMElement).append("svg")
        .attr("width", svgWidth)
        .attr("height", svgHeight);

    var tooltip = d3.select(DOMElement).append("div")
        .classed("tooltip", true);

    // scales
    var xScale = d3.scaleBand(),
        yScale = d3.scaleLinear();

    // data
    var dataset = [];

    // interaction settings
    var tooltipText = function(d, i){return "tooltip over element "+i;}
    var mouseoverCallback = function(d, i){ };
    var mouseoutCallback = function(d, i){ };
    var mouseclickCallback = function(d, i){ console.log(d,i)};
    var keySelected = null;

    // ---- PRIVATE FUNCTIONS

    function render(){

        svg.attr("width", svgWidth)
            .attr("height", svgHeight);

        updateScales();

        GUP_bars();

        updateInteractions();
        updateStyles();

    }

    function updateScales(){
        xScale.domain(dataset.map(function(d){return d.key;}))
            .paddingInner(0.1)
            .range([svgPadding, svgWidth-svgPadding]);

        yScale.domain([0, d3.max(dataset, function(d){return d.value;})])
            .range([0, svgHeight-svgPadding*2]);
    }

    function GUP_bars(){

        // transitions
        var increments = 300;
        var t1 = d3.transition().duration(increments),
            t2 = d3.transition().delay(increments).duration(increments),
            t3 = d3.transition().delay(increments*2).duration(increments),
            t4 = d3.transition().delay(increments*3).duration(increments);

        // GUP
        var bars = svg.selectAll("rect.bar") // Selection
            .data(dataset, d=>d.key) // Bind

        // exit
        bars.exit().transition(t1)
            .attr("y", svgHeight-svgPadding)
            .attr("height", 0)
            .remove();

        // enter 
        bars.enter().append("rect")
            .classed("bar", true)
            .attr("x", d=>xScale(d.key))
            .attr("width", xScale.bandwidth())
            .attr("height", 0)
            .attr("y", svgHeight-svgPadding)
            .transition(t4)
            .attr("y", d=>svgHeight-svgPadding-yScale(d.value))
            .attr("height", d=>yScale(d.value));

        // update
        bars.transition(t2)
            .attr("y", d=>svgHeight-svgPadding-yScale(d.value))
            .attr("height", d=>yScale(d.value))
            .transition(t3)
            .attr("x", d=>xScale(d.key))
            .attr("width", xScale.bandwidth());
    }

    function updateStyles(){
        // separate function for styles,
        // this way there is no need to do GUP when just changing colour
        svg.selectAll("rect.bar")
            .style("fill", barColor)
            .style("stroke", "#424242")
            .style("stroke-width", d=>keySelected == d.key ? "5px": "0px")
            .style("opacity", 0.7)
    }

    function updateInteractions(){
        // separate function for interactions,
        // this way there is no need to do GUP when just changing callbacks
        svg.selectAll("rect.bar")
            .on("mouseover", function(d, i){
                d3.select(this).style("opacity", 1);

                tooltip.html(tooltipText(d,i))
                    .style("left", (d3.event.pageX) + "px")     
                    .style("top", (d3.event.pageY - 28) + "px")
                    .style("opacity", 0.9);

                mouseoverCallback(d, i);
            })
            .on("mouseout", function(d, i){
                d3.select(this).style("opacity", 0.7);

                tooltip.style("opacity", 0);

                mouseoutCallback(d, i);

            })
            .on("click", function(d, i) {

            var color = ["#009688","#968118","#009688",];
            var p = d3.select("#pie1").selectAll(".arc");
            console.log(p);
            p
                .data(p.pie(dataManager.getArea(d.key)))
                .enter().append("p")
                .attr("class","arc")
                render();

             console.log(p);
            })








    }


    return barObj; // returning the main object
}
链接地址: http://www.djcxy.com/p/84206.html

上一篇: 有没有办法限制Firebase中的注册

下一篇: 单击重绘d3饼图