12

我正在d3中进行可视化。它涉及在地图上的国家上绘制圆圈,然后缩放圆圈的大小以与有关这些国家的数据相对应。我想随着圆的半径变大而改变不透明度,但是我的代码不起作用,尽管进行了大量的实验和调整。有人可以指出我在这里缺少什么吗?

我将在下面发布整个代码,以防万一。向下滚动到 showJan 函数以查看我尝试过的操作(不起作用)。提前谢谢了。

<div id="viz">
</div>


<div id="cal">
</div>
<a href='#' class='jan'>January</a>
<a href='#' class='feb'>February</a>
<a href='#' class='mar'>March</a>
<a href='#' class='apr'>April</a>
<a href='#' class='may'>May</a>
<a href='#' class='june'>June</a>
<a href='#' class='july'>July</a>
<a href='#' class='aug'>August</a>
<a href='#' class='sept'>September</a>
<a href='#' class='oct'>October</a>
<a href='#' class='nov'>November</a>
<a href='#' class='dec'>December</a>

<script>
  var height = 530;
  var width = 860;
  var svg = d3.select('#viz').append('svg')
                                .attr('height', height)
                                .attr('width', width)

  var countriesData = window.countriesData;
  // This is a big list of all the countries in the world 
  // in a format that d3 likes

  // The skyscanner flight data.
  var sizeData = window.skyscanner;

  // A scale to manage the size of the circles.
  var rScale = d3.scale.log();
  rScale.domain([1, 50000]).range([1, 100])

  // A scale to manage the opacity of the circles.
  var oScale = d3.scale.log();
  oScale.domain([1, 50000]).range([.6, 0])


</script>


<script>
  // Setup a mercator projection
  // A projection is a bit like a scale except it maps 
  // latitudes and longitudes to pixels
  // There are a lot of projections:
  // https://github.com/mbostock/d3/wiki/Geo-Projections

  var projection = d3.geo.mercator()
                           .scale(880)
                           .translate([410, 340])


  // Setup a geo path
  // A path is a magical path drawer, that can take things
  // listed in a geo format called geojson (lots of geo data
  // is formatted like this) and draws those shapes onto your
  // projection

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


  // Take our loaded big list of countries and draw it
  // using our path
  //
  // All countries are under a 'countries' group
  // to make them easier to work with
  //
  // The 'path' element is just 
  // a freeform path that joins points to make a shape.
  //
  // The 'path' generator that we pass to .attr('d', path) takes
  // the geo data and draws a path

  var countries = svg.append('g') // make a group to hold them all

  countries.selectAll('path')
              .data(countriesData.features)
              .enter()
              .append('path')
              .attr('d', path) // uses our path to draw the countries


  function calculateCountryCenter(country) {
    var coords;

    //If the country has more than one bounding region (like the usa has
    //the main usa, alaska and hawaii, use the first one)
    //Otherwise just use the only list
    if (country.geometry.coordinates.length > 1) {

        console.log("length " + country.geometry.coordinates.length);
        console.log("name " + country.name);
        console.log("size of first region " + country.geometry.coordinates[0].area);


        for (index = 0; index < country.geometry.coordinates.length; index++) {
        console.log(country.geometry.coordinates[index].area)
        }

        coords = country.geometry.coordinates[0][0]; 

    } else {
        coords = country.geometry.coordinates[0];
    }

    var averageCoords = [0,0];
    coords.forEach(function(coord) {
      averageCoords[0] += coord[0]
      averageCoords[1] += coord[1]
    });


    averageCoords[0] = averageCoords[0] / coords.length
    averageCoords[1] = averageCoords[1] / coords.length
    return averageCoords;
  }


  var countryCirclesGroup = svg.append('g') // a group to hold our circles

  // Bind the data to the country circles group. Bind on country id (see json file)
  var countryCircles = countryCirclesGroup.selectAll('circle')
                        .data(countriesData.features, function(country) 
                        { return country.id })

  // Enter a circle for each data point, with pos. at x and y coords.   
  countryCircles.enter().append('circle')
                  .attr('r', 0)
                  .attr('cx', function(country) {
                    var center = calculateCountryCenter(country);
                    return projection(center)[0] // return x coord of mapped center
                  })
                  .attr('cy', function(country) {
                    var center = calculateCountryCenter(country);
                    return projection(center)[1] // return y coord of mapped center
                  })
                  .style('fill', 'black')
                  .style('opacity', .15)
                  .on('click', function(country) { alert(country.properties.name) })


    // Functions for the month buttons.
    function showJan() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Jan + 1) })
                .style('opacity', function(dataPoint) { return oScale(dataPoint.Jan + 1) })
    }

    function showFeb() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Feb + 1) })                
    }

    function showMar() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Mar + 1) })    
    }   

    function showApr() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Apr + 1) })
    }       

    function showMay() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.May + 1) })
    }  

    function showJune() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Jun + 1) })
    }

    function showJuly() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Jul + 1) })
    }                   

    function showAug() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Aug + 1) })
    }   

    function showSept() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Sep + 1) })
    }   

    function showOct() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Oct + 1) })
    }   

    function showNov() {

        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Nov + 1) })
    }

    function showDec() {

        // This sets the circles with size data as a certain size and as red.
        countryCirclesGroup.selectAll('circle')
            .data(sizeData, function(dataPoint) { return dataPoint.name })
                .transition().duration(1000)
                .attr('r', function(dataPoint) { return rScale(dataPoint.Dec + 1) })
    }       

  // A reset function for debugging help. Rewrite to show Jan sizes.
  function reset() {
        countryCirclesGroup.selectAll('circle')
            .data(sizeData)
            .transition().duration(1000)
            .attr('r', 0)
  }                     


  d3.select('a.jan').on('click', showJan)
  d3.select('a.feb').on('click', showFeb)
  d3.select('a.mar').on('click', showMar)
  d3.select('a.apr').on('click', showApr)
  d3.select('a.may').on('click', showMay)
  d3.select('a.june').on('click', showJune)
  d3.select('a.july').on('click', showJuly)
  d3.select('a.aug').on('click', showAug)
  d3.select('a.sept').on('click', showSept)
  d3.select('a.oct').on('click', showOct)
  d3.select('a.nov').on('click', showNov)
  d3.select('a.dec').on('click', showDec)

</script>

<script>
    //Don't delete this
    reset();
</script>

4

1 回答 1

11

transitionand之后duration,您必须更新将要更改的属性。代码示例:

var svg = d3.select("body").append("svg");

svg
  .attr('id','mySVG')
  .attr('width', '100%')
  .attr('height', '100%');

// Set the initial properties of the circles
var circle = svg.selectAll('circle')
    .data([2, 5, 8])
    .enter()
    .append('circle')
        .attr('cx', function(item) { return item; })
        .attr('cy', function(item) { return item; })
        .attr('r', 0)
        .attr('fill', '#babdb6');

// Update the attributes that will change
circle
    .transition()
    .duration(2000)
        .attr('fill-opacity', 0.2)
        .attr('r', function(item) { return 100 * item; });

我写了一个可以帮助你的最小例子。http://jsfiddle.net/pnavarrc/udMUx/

于 2013-04-13T16:46:31.650 回答