如何更改 d3 中圆的半径和不透明度?

Posted

技术标签:

【中文标题】如何更改 d3 中圆的半径和不透明度?【英文标题】:How can I change the radius and opacity of a circle in d3? 【发布时间】:2013-04-05 23:45:28 【问题描述】:

我正在 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>

【问题讨论】:

【参考方案1】:

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

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/.

【讨论】:

这让我找到了正确的方向,我现在已经开始工作了。非常感谢!

以上是关于如何更改 d3 中圆的半径和不透明度?的主要内容,如果未能解决你的问题,请参考以下文章

将圆的半径(以米为单位)缩放到 D3.js d3.geo.mercator 地图

leaflet 如何绘制圆

d3.js画圆弧和圆的坐标、弧长计算方法

z-index 和不透明度 - 如何隐藏 div

Javascript删除背景颜色和不透明度

具有延迟和不透明度的 CSS 动画