d3.js:基于多个圆圈图表的Zoomable / Pannable

时间:2013-07-26 09:28:58

标签: path d3.js focus geometry

对不起,如果标题或我的解释不好,法语中的问题就不容易了,所以用英语...

所以,我尝试制作一个类似于Focus+Context via Brushing的图表,但是,我没有一条显示数据的路径,而是500圈。 暂时,Zoom和Pan不工作。 根据我对问题的理解,我需要将我的500圈转换为单一路径,但我不知道如何做到这一点,如果它是好的解决方案或事件,如果可能的话......

感谢您的帮助,这是一个小提琴(我的第一个):http://jsfiddle.net/Kazual/R96Kc/

代码:(我给出了所有的代码,但这只是我需要修复的泛效应,所有数据都是随机的,并不代表任何东西,并使用右下方的3按钮更新圆位置)< / p>

    function graphiqueCircle(x, y, w, h, trgDiv){
    graphiqueCircle.C_INDICE_VIE = "Indice Vie";
    graphiqueCircle.C_INDICE_SANTE = "Indice Sante";
    graphiqueCircle.C_INDICE_INSTRUCTION = "Indice Instruction";

    var indiceVie = false,
        indiceSante = false,
        indiceInstruction = false;
    var margin = {top: y, right: 0, bottom: 0, left: x},
        width = w,
        height = h,
        height2 = 20;
    //
    var x = d3.scale.linear()
                .range([0, width]);
    var y = d3.scale.linear()
                .range([height, 0]);
    var x2 = d3.scale.linear()
                .range([0, width]);
    var y2 = d3.scale.linear()
                .range([height2, 0]);
    //
    var color = d3.scale.category10();
    //
    var xAxis = d3.svg.axis()
                .scale(x)
                .orient("bottom");
    var yAxis = d3.svg.axis()
                .scale(y)
                .orient("left");
    var xAxis2 = d3.svg.axis()
                .scale(x2)
                .orient("bottom");
    //
    var brush = d3.svg.brush()
                .x(x2)
                .on("brush", brushed);
    //
    var area = d3.svg.area()
                .interpolate("monotone")
                .x(function(d) {    return x(d.codeCom);    })
                .y0(height)
                .y1(function(d) {   return [0,1];           });
    var area2 = d3.svg.area()
                .interpolate("monotone")
                .x(function(d) {    return x2(d.codeCom);   })
                .y0(height2)
                .y1(function(d) {   return [0,1];           });
    //
    var svg = d3.select(trgDiv).append("svg").attr("class", "gMap")
                .attr("width", width + 50 )
                .attr("height", height + 50 + height2 +50);
    //
    svg.append("defs").append("clipPath")
        .attr("id", "clip")
        .append("rect")
            .attr("width", width)
            .attr("height", height);
    //
    var allCircles,
        allCirclesContext,
        theckBox,
        axeX,
        axeY,
        _data;
    //
    var focus = svg.append("g")
        .attr("transform", "translate(" + (margin.left + 10) + "," + margin.top + ")")
    var context = svg.append("g")
        .attr("transform", "translate(" + (margin.left + 10) + "," + (margin.top+height+height2+30) + ")")
    //
        _data = [
        {codeCom:33001, communes:"obj1", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib1"},
        {codeCom:33002, communes:"obj2", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib2"},
        {codeCom:33003, communes:"obj3", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib3"},
        {codeCom:33004, communes:"obj4", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib4"},
        {codeCom:33005, communes:"obj5", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib5"},
        {codeCom:33006, communes:"obj6", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib6"},
        {codeCom:33007, communes:"obj7", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib7"},
        {codeCom:33008, communes:"obj8", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib8"},
        {codeCom:33009, communes:"obj9", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib9"}
        ]
        _data.forEach(function(d) {             
            d.IDH4 = (d.IDH4 != "NULL") ? +d.IDH4 : 0;
            d.indiceVie = (d.indiceVie != "NULL") ? +d.indiceVie : 0;
            d.indiceSante = (d.indiceSante != "NULL") ? +d.indiceSante : 0;
            d.indiceInstruction = (d.indiceInstruction != "NULL") ? +d.indiceInstruction : 0;
            d.codeCom = (d.codeCom != "NULL") ? +d.codeCom : 0;
        });
        //
        x.domain(d3.extent(_data.map(function(d) { return d.codeCom; })));
        y.domain([0,1]);
        x2.domain(x.domain());
        y2.domain(y.domain());
        //
        allCircles = focus.append("g");
        allCircles.attr("id", "allCicles")
                .datum(_data)
                .attr("clip-path", "url(#clip)")
                .attr("d", area)
            .selectAll(".dot")
            .data(_data)
            .enter().append("circle")
                .attr("class", "dot")
                .attr("id", function(d){    return d.communes;  })
                .attr("r", 3.5)
                .attr("cx", function(d) { return x(d.codeCom); })
                .attr("cy", function(d) { return 0; })
                .style("fill", function(d) { return color(d.LIBSCOT); });

        focus.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis)
                .append("text")
                .attr("class", "label")
                .attr("x", width)
                .attr("y", -6)
                .style("text-anchor", "end")
                .text("Communes");

        focus.append("g")
            .attr("class", "y axis")
            .call(yAxis)
                .append("text")
                .attr("class", "label")
                .attr("transform", "rotate(-90)")
                .attr("y", 6)
                .attr("x", -6)
                .attr("dy", ".71em")
                .style("text-anchor", "end")
                .text("Indice");

        allCirclesContext = context.append("g");
        allCirclesContext.attr("id", "allCirclesContext")
                .datum(_data)
                .attr("d", area2)
            .selectAll(".dot")
            .data(_data)
            .enter().append("circle")
                .attr("class", "dot")
                .attr("id", function(d){    return d.communes;  })
                .attr("r", 2)
                .attr("cx", function(d) { return x2(d.codeCom); })
                .attr("cy", function(d) { return 0; })
                .style("fill", function(d) { return color(d.LIBSCOT); });

        context.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height2 + ")")
            .call(xAxis2);
        //
        context.append("g")
            .attr("transform", function(d, i) { return "translate(0,-20)"; })
            .style("fill", "blue")
            .attr("class", "x brush")
            .call(brush)
            .selectAll("rect")
                .attr("y", -6)
                .attr("height", height2 + 7)
                .style("fill-opacity", .2)
                .style("visibility", "visible");
        //
        // LEGEND & CHEKBOX
        var legend = focus.selectAll(".legend")
            .data(color.domain())
                .enter().append("g")
                .attr("class", "legend")
                .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
        legend.append("rect")
            .attr("x", width - 18)
            .attr("width", 18)
            .attr("height", 18)
            .style("fill", color);
        legend.append("text")
            .attr("x", width - 24)
            .attr("y", 9)
            .attr("dy", ".35em")
            .style("text-anchor", "end")
            .text(function(d) { return d; });
        //
        createTchekBox();

    function createTchekBox(){
        theckBox = focus.selectAll(".theckBox")
            .data(["Indice Vie", "Indice Sante", "Indice Instruction"])
                .enter().append("g")
                .attr("class", "theckBox")
                .attr("transform", function(d, i) { return "translate(0," + ((i * 20)+300) + ")"; });
        theckBox.append("rect")
            .attr("isClicked", "false")
            .attr("id", function(d) { return d; })
            .attr("x", width - 18)
            .attr("width", 18)
            .attr("height", 18)
            .style("fill", "black")
            .on("mouseover", function(){
                d3.select(this).style("fill", "grey");
            })
            .on("mouseout", function(){
                if(d3.select(this).attr("isClicked") == "false")
                    d3.select(this).style("fill", "black");
                else
                    d3.select(this).style("fill", "red");
            })
            .on("click", function(){
                if(d3.select(this).attr("isClicked") == "false"){
                    d3.select(this).style("fill", "red");
                    d3.select(this).attr("isClicked", "true");
                }else{
                    d3.select(this).style("fill", "black");
                    d3.select(this).attr("isClicked", "false");
                }
                if(d3.select(this).attr("id") == "Indice Vie")
                    indiceVie = !indiceVie;
                else if(d3.select(this).attr("id") == "Indice Sante")
                    indiceSante = !indiceSante;
                else if(d3.select(this).attr("id") == "Indice Instruction")
                    indiceInstruction = !indiceInstruction;
                //
                onUpdate();
            });
        theckBox.append("text")
            .attr("x", width - 24)
            .attr("y", 9)
            .attr("dy", ".35em")
            .style("text-anchor", "end")
            .text(function(d) { return d; });
    }
    function brushed() {
        x.domain(brush.empty() ? x2.domain() : brush.extent());
        focus.select("#allCicles").attr("d", area);
        focus.select(".x.axis").call(xAxis);
    }
    function onUpdate(){
        var data1,
            data2,
            data3;
        //
        if(indiceVie)
            data1 = graphiqueCircle.C_INDICE_VIE;
        else
            data1 = null;
        if(indiceSante)
            data2 = graphiqueCircle.C_INDICE_SANTE;
        else
            data2 = null;
        if(indiceInstruction)
            data3 = graphiqueCircle.C_INDICE_INSTRUCTION;
        else
            data3 = null;
        //
        allCircles.selectAll(".dot").each(function(d, i){
            d3.select(this).transition().duration(400).delay(i*1)
                .attr("cy", function(d, i) {
                    var returnValue = 0;
                    var diviseur = 0;
                    if(data1 == graphiqueCircle.C_INDICE_VIE){
                        returnValue += y(d.indiceVie);
                        diviseur++;
                    }
                    if(data2 == graphiqueCircle.C_INDICE_SANTE){
                        returnValue += y(d.indiceSante);
                        diviseur++;
                    }
                    if(data3 == graphiqueCircle.C_INDICE_INSTRUCTION){
                        returnValue += y(d.indiceInstruction);
                        diviseur++;
                    }
                    if(diviseur == 0)
                        return 0;
                    return returnValue/diviseur;
            });
        });
        allCirclesContext.selectAll(".dot").each(function(d, i){
            d3.select(this).transition().duration(400).delay(i*1)
                .attr("cy", function(d, i) {
                    var returnValue = 0;
                    var diviseur = 0;
                    if(data1 == graphiqueCircle.C_INDICE_VIE){
                        returnValue += y2(d.indiceVie);
                        diviseur++;
                    }
                    if(data2 == graphiqueCircle.C_INDICE_SANTE){
                        returnValue += y2(d.indiceSante);
                        diviseur++;
                    }
                    if(data3 == graphiqueCircle.C_INDICE_INSTRUCTION){
                        returnValue += y2(d.indiceInstruction);
                        diviseur++;
                    }
                    if(diviseur == 0)
                        return 0;
                    return returnValue/diviseur-20;
            });
        });

    }
}
var _myGraphique = new graphiqueCircle(20, 20, 800, 400, ".div_iMap");

0 个答案:

没有答案