简体   繁体   English

尝试使用D3在地图上获取圆圈以转换为条形图中的条形图

[英]Trying to get circles on map to transition into bars in bar chart with D3

I create a bubble map with D3, and I want the user to be able to click on a button and the circles on the map will transition into bars of a bar chart. 我用D3创建一个气泡图,我希望用户能够单击一个按钮,并且图上的圆圈将转变为条形图的条形图。 I am using the enter, update, exit pattern, but right now what I have isn't working as the bar chart is drawn on top and all the bars and circles are translated, instead of the circles transitioning into bars and the bars being translated into place. 我正在使用输入,更新,退出模式,但是现在我无法使用,因为条形图绘制在顶部,并且所有条形和圆形都已翻译,而不是将圆形过渡为条形和正在翻译的条形到位。 Below is the relevant part of my code, and here is the link to the demo: https://jhjanicki.github.io/circles-to-bars/ 以下是我的代码的相关部分,这是演示的链接: https : //jhjanicki.github.io/circles-to-bars/

var projection = d3.geo.mercator()
  .scale(150)
  .center([20, 40])
  .translate([width / 2, height / 2]);

 var path= d3.geo.path()
  .projection(projection);

 var features = countries2.features;   

 d3.csv("data/sum_by_country.csv", function(error, data) {

        data.sort(function(a,b){
                return a.value - b.value;
          });

        var myfeatures= joinData(features, data, ['value']);


        var worldMap = svg.append('g');
        var world = worldMap.selectAll(".worldcountries")
                .data(myfeatures)
                .enter()
                .append("path")
                .attr("class", function(d){
                    return "World " + d.properties.name+" worldcountries";
                })
                .attr("d", path)
                .style("fill", "#ddd")
              .style("stroke", "white")
              .style("stroke-width", "1");

        var radius =  d3.scale.sqrt()
                .domain([0,1097805])
                .range([3, 20]);

        var newFeatures = [];
        myfeatures.forEach(function(d){
            if(d.properties.hasOwnProperty("value")){
                console.log(d.properties.name);
                newFeatures.push(d);
            }

        });


        newFeatures.sort(function(a,b){
                return b.properties.value - a.properties.value;
          });


        var bubbles = svg.append("g").classed("bubbleG","true");

        bubbles.selectAll("circle")
            .data(newFeatures)
            .enter().append("circle")
            .attr("class", "bubble")
            .attr("transform", function(d) { 
                return "translate(" + path.centroid(d) + ")"; 
            })
            .attr("r", function(d){
                return radius(d.properties.value);
            })
            .attr("fill","#2166ac")
            .attr("stroke","white")
            .attr("id", function(d){
                return "circle "+d.properties.name;
            });


             $('#bubblebar').click(function(){
                mapBarTransition(newFeatures,bubbles)
            });

    });




// button onclick
function mapBarTransition(data,bubbles){

        var margin = {top:20, right:20, bottom:120, left:80},
        chartW = width - margin.left - margin.right,
        chartH = height - margin.top - margin.bottom;

        var x = d3.scale.ordinal()
                .domain(data.map(function(d) { return d.properties.name; }))
                .rangeRoundBands([0, chartW], .4);
        var y = d3.scale.linear()
                .domain([0,1097805])
                .nice()
                .range([chartH,0]);

        var xAxis = d3.svg.axis()
                    .scale(x)
                    .orient("bottom");

        var yAxis = d3.svg.axis()
                    .scale(y)
                    .ticks(8)
                    .orient("left");

        var barW = width / data.length;


                bubbles.append("g").classed("bubblebar-chart-group", true);
                bubbles.append("g").classed("bubblebar-x-axis-group axis", true);
                bubbles.append("g").classed("bubblebar-y-axis-group axis", true);

            bubbles.transition().duration(1000).attr({transform: "translate(" + margin.left + "," + margin.top + ")"});

            bubbles.select(".bubblebar-x-axis-group.axis")
                .attr({transform: "translate(0," + (chartH) + ")"})
                .call(xAxis)
                .selectAll("text")  
                .style("text-anchor", "end")
                .attr("dx", "-.8em")
                .attr("dy", ".15em")
                .attr("transform", function(d) {
                    return "rotate(-65)" 
                    });


            bubbles.select(".bubblebar-y-axis-group.axis")
                .transition()
                .call(yAxis);


            barW = x.rangeBand();

            var bars = bubbles.select(".bubblebar-chart-group")
                    .selectAll(".bubble")
                    .data(data);

            bars.enter().append("rect")
                .classed("bubble", true)
                .attr("x", function(d) { return x(d.properties.name); })
                .attr("y", function(d) { return y(d.properties.value); })
                .attr("width", barW)
                .attr("height", function(d) { return chartH - y(d.properties.value); })
                .attr("fill","#2166ac");


            bars.transition()
                .attr("x", function(d) { return x(d.properties.name); })
                .attr("y", function(d) { return y(d.properties.value); })
                .attr("width", barW)
                .attr("height", function(d) { return chartH - y(d.properties.value); });


            bars.exit().transition().style({opacity: 0}).remove();


}

And here is the repo for your reference: https://github.com/jhjanicki/circles-to-bars 这是供您参考的存储库: https : //github.com/jhjanicki/circles-to-bars

First, you have two very different selections with your circles and bars. 首先,您的圆圈和条形有两个非常不同的选择。 They are in separate g containers and when you draw the bar chart, you aren't even selecting the circles. 它们位于单独的g容器中,绘制条形图时,您甚至都没有选择圆圈。

Second, I'm not sure that d3 has any built-in way to know how to transition from a circle element to a rect element. 其次,我不确定d3是否有任何内置方法来知道如何从圆形元素过渡到rect元素。 There's some discussion here and here 这里这里有一些讨论

That said, here's a quick hack with your code to demonstrate one way you could do this: 就是说,这是您的代码的快速破解,以演示您可以执行此操作的一种方法:

 <!DOCTYPE html> <head> <meta charset="utf-8"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel='stylesheet'> <link href="//rawgit.com/jhjanicki/circles-to-bars/master/css/style.css" rel='stylesheet'> <!-- Roboto & Asar CSS --> <link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'> <link href="https://fonts.googleapis.com/css?family=Asar" rel="stylesheet"> </head> <body> <button type="button" class="btn btn-primary" id="bubblebar">Bar Chart</button> <div id="chart"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> <!-- D3.geo --> <script src="https://d3js.org/d3.geo.projection.v0.min.js"></script> <!-- jQuery --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="//rawgit.com/jhjanicki/circles-to-bars/master/data/countries2.js"></script> <script> window.onload = function() { // set up svg and scrolling var width = window.innerWidth / 2; var height = window.innerHeight; var svg = d3.select("#chart").append("svg") .attr('width', width) .attr('height', height); var bubbleMapState = 'map'; // map or bar var projection = d3.geo.mercator() .scale(150) .center([20, 40]) .translate([width / 2, height / 2]); var path = d3.geo.path() .projection(projection); var features = countries2.features; d3.csv("//rawgit.com/jhjanicki/circles-to-bars/master/data/sum_by_country.csv", function(error, data) { data.sort(function(a, b) { return a.value - b.value; }); var myfeatures = joinData(features, data, ['value']); var worldMap = svg.append('g'); var world = worldMap.selectAll(".worldcountries") .data(myfeatures) .enter() .append("path") .attr("class", function(d) { return "World " + d.properties.name + " worldcountries"; }) .attr("d", path) .style("fill", "#ddd") .style("stroke", "white") .style("stroke-width", "1"); var radius = d3.scale.sqrt() .domain([0, 1097805]) .range([3, 20]); var newFeatures = []; myfeatures.forEach(function(d) { if (d.properties.hasOwnProperty("value")) { console.log(d.properties.name); newFeatures.push(d); } }); newFeatures.sort(function(a, b) { return b.properties.value - a.properties.value; }); var bubbles = svg.append("g").classed("bubbleG", "true"); bubbles.selectAll("rect") .data(newFeatures) .enter().append("rect") .attr("class", "bubble") .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; }) .attr("width", function(d) { return radius(d.properties.value) * 2; }) .attr("height", function(d){ return radius(d.properties.value) * 2; }) .attr("rx", 20) .attr("fill", "#2166ac") .attr("stroke", "white") .attr("id", function(d) { return "circle " + d.properties.name; }); $('#bubblebar').click(function() { mapBarTransition(newFeatures, bubbles) }); }); // button onclick function mapBarTransition(data, bubbles) { if (bubbleMapState == 'map') { bubbleMapState == 'bar'; } else { bubbleMapState == 'map'; } var margin = { top: 20, right: 20, bottom: 120, left: 80 }, chartW = width - margin.left - margin.right, chartH = height - margin.top - margin.bottom; var x = d3.scale.ordinal() .domain(data.map(function(d) { return d.properties.name; })) .rangeRoundBands([0, chartW], .4); var y = d3.scale.linear() .domain([0, 1097805]) .nice() .range([chartH, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .ticks(8) .orient("left"); var barW = width / data.length; bubbles.append("g").classed("bubblebar-chart-group", true); bubbles.append("g").classed("bubblebar-x-axis-group axis", true); bubbles.append("g").classed("bubblebar-y-axis-group axis", true); bubbles.transition().duration(1000).attr({ transform: "translate(" + margin.left + "," + margin.top + ")" }); bubbles.select(".bubblebar-x-axis-group.axis") .attr({ transform: "translate(0," + (chartH) + ")" }) .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", function(d) { return "rotate(-65)" }); bubbles.select(".bubblebar-y-axis-group.axis") .transition() .call(yAxis); barW = x.rangeBand(); var bars = d3.select(".bubbleG") .selectAll(".bubble") .data(data); bars.enter().append("rect") .classed("bubble", true) .attr("x", function(d) { return x(d.properties.name); }) .attr("y", function(d) { return y(d.properties.value); }) .attr("width", barW) .attr("height", function(d) { return chartH - y(d.properties.value); }) .attr("fill", "#2166ac"); bars.transition() .duration(1000) .attr("transform", function(d){ return "translate(" + x(d.properties.name) + "," + y(d.properties.value) + ")"; }) .attr("rx", 0) .attr("width", barW) .attr("height", function(d) { return chartH - y(d.properties.value); }); bars.exit().transition().style({ opacity: 0 }).remove(); } function joinData(thisFeatures, thisData, DataArray) { //loop through csv to assign each set of csv attribute values to geojson counties for (var i = 0; i < thisData.length; i++) { var csvCountry = thisData[i]; //the current county var csvKey = csvCountry.Country; //the CSV primary key //loop through geojson regions to find correct counties for (var a = 0; a < thisFeatures.length; a++) { var geojsonProps = thisFeatures[a].properties; //the current region geojson properties var geojsonKey = geojsonProps.name; //the geojson primary key //where primary keys match, transfer csv data to geojson properties object if (geojsonKey == csvKey) { //assign all attributes and values DataArray.forEach(function(attr) { var val = parseFloat(csvCountry[attr]); //get csv attribute value geojsonProps[attr] = val; //assign attribute and value to geojson properties }); }; }; }; return thisFeatures; }; } </script> </body> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM