最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - D3.js Pie chart .. can pie slice move when selected? - Stack Overflow

programmeradmin5浏览0评论

Just wondering is it possible to do something like this with d3?

/

Where when you click on a certain pie slice the slice moves on click?

Have the pie created up to this point just wondering if I can add this feature

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

.arc path {
  stroke: #fff;
}

</style>
<body>
<script src=".v3.min.js"></script>
<script>

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

var color = d3.scale.ordinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

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

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

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

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

  data.forEach(function(d) {
    d.population = +d.population;
  });

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

  g.append("path")
      .attr("d", arc)
      .style("fill", function(d) { return color(d.data.age); });

  g.append("text")
      .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .text(function(d) { return d.data.age; });

});

</script>

Data is coming from a csv file.

Thanks

Just wondering is it possible to do something like this with d3?

http://jsfiddle.net/8T7Ew/

Where when you click on a certain pie slice the slice moves on click?

Have the pie created up to this point just wondering if I can add this feature

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

.arc path {
  stroke: #fff;
}

</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

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

var color = d3.scale.ordinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

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

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

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

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

  data.forEach(function(d) {
    d.population = +d.population;
  });

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

  g.append("path")
      .attr("d", arc)
      .style("fill", function(d) { return color(d.data.age); });

  g.append("text")
      .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .text(function(d) { return d.data.age; });

});

</script>

Data is coming from a csv file.

Thanks

Share Improve this question asked Oct 7, 2014 at 10:53 bp2010bp2010 2,47223 silver badges36 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 11

You can increase the arc radius of pie for highlighting. JSFiddle

var arcOver = d3.svg.arc()
    .outerRadius(r + 10);

g.append("path")
   .attr("d", arc)
   .style("fill", function(d) { return color(d.data.age); })
   .on("mouseenter", function(d) {
        d3.select(this)
           .attr("stroke","white")
           .transition()
           .duration(1000)
           .attr("d", arcOver)             
           .attr("stroke-width",6);
    })
    .on("mouseleave", function(d) {
        d3.select(this).transition()            
           .attr("d", arc)
           .attr("stroke","none");
    });

I prefer changing Radius rather than stroke as it gives you smooth and nicer animation...

Using a function like this:

function pathEnter() {
  t = d3.select(this);
  t.transition()
  .attr('d', pathIn);
}

Run this code below to see the interaction:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  .arc text {
    font: 10px sans-serif;
    text-anchor: middle;
  }
  
  .arc path {
    stroke: #fff;
  }
</style>
<svg width="520" height="280"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
  var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius = Math.min(width, height) / 2 - 20,
    g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");


  var color = d3.scaleOrdinal(d3.schemeCategory10);

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

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

  var pathIn = d3.arc()
    .outerRadius(radius + 6)
    .innerRadius(0);


  function pathEnter() {
    t = d3.select(this);
    t.transition()
      .attr('d', pathIn);
  }

  function pathOut() {
    t = d3.select(this);
    t.transition()
      .attr('d', path);
  }

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


  data = [{
      age: '<5',
      population: '2704659'
    },
    {
      age: '5-13',
      population: '4499890'
    },
    {
      age: '14-17',
      population: '2159981'
    },
    {
      age: '18-24',
      population: '3853788'
    },
    {
      age: '25-44',
      population: '14106543'
    },
    {
      age: '45-64',
      population: '8819342'
    },
    {
      age: '≥65',
      population: '612463'
    },
  ];

  data.population = +data.population;

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


  arc.append("path")
    .attr("d", path)
    .on('mouseenter', pathEnter)
    .on('mouseout', pathOut)
    .attr("fill", function(d) {
      return color(d.data.age);
    });

  arc.append("text")
    .attr("transform", function(d) {
      return "translate(" + label.centroid(d) + ")";
    })
    .attr("dy", "0.35em")
    .text(function(d) {
      return d.data.age;
    });
</script>

Using the attribute transform="translate(x, y)" would do the actual moving of each slice of the pie.

http://jsfiddle.net/qkHK6/3306/

Building on @Gilsha's answer (I know this question is old, but I figured I'd put this answer up for archival purposes)...

g.append("path")
    .attr("d", arc)
    .attr("opacity", "1.0")
    .on("mouseenter", function (d) {
        var arcOver = d3.arc()
            .outerRadius(radius).innerRadius(0).startAngle(d.startAngle + 0.01).endAngle(d.endAngle - 0.01);
        var transformText = getTranslate(d.startAngle + 0.01, d.endAngle - 0.01, 20);

        d3.select(this)
            .attr("d", arcOver)
            .transition()
            .duration(200).ease(d3.easeBack)
            .attr("transform", transformText)
            .attr("style", "fill: rgb(102, 102, 102)");
    })
    .on("mouseleave", function (d) {
        d3.select(this)
            .attr("d", arc)
            .transition().ease(d3.easeBack)
            .duration(600)
            .attr("transform", "translate(0,0)")
            .attr("style", "fill: " + color(d.data));
    })
    .style("fill", function (d) { return color(d.data); });

Also d3.arc() is from version 4.

Helper methods below:

getTranslate = function (startAngle, endAngle, distance) {
    var xTranslate, yTranslate;
    var startQ = getQuadrant(startAngle);
    var endQ = getQuadrant(endAngle);

//Assume there are 7 possibilities since last slice always ends at Tau or 12 o'clock when doing a d.endAngle
    switch (true) {
        case (startQ == 1 && endQ == 1):
            xTranslate = distance * 0.5;
            yTranslate = distance * -1.5;
            break;
        case (startQ == 1 && endQ == 4):
            xTranslate = distance * 1.5;
            yTranslate = distance * 0.5;
            break;
        case (startQ == 4 && endQ == 4):
            xTranslate = distance * 0.5;
            yTranslate = distance * 1.5;
            break;
        case (startQ == 4 && endQ == 3):
            xTranslate = distance * -0.5;
            yTranslate = distance * 1.5;
            break;
        case (startQ == 3 && endQ == 3):
            xTranslate = distance * -1.5;
            yTranslate = distance * 0.5;
            break;
        case (startQ == 3 && endQ == 2):
            xTranslate = distance * -1.5;
            yTranslate = distance * -0.5;
            break;
        case (startQ == 2 && endQ == 2):
            xTranslate = distance * -0.5;
            yTranslate = distance * -1.5;
            break;
    }

    return "translate(" + xTranslate + "," + yTranslate + ")";
}

getQuadrant = function (angle) {
    switch (true) {
        case angle < (Math.PI * 0.5):
            return 1;
            break;
        case angle >= (Math.PI * 1.5):
            return 2;
            break;
        case ((Math.PI < angle) && angle <= (Math.PI * 1.5)):
            return 3;
            break;
        default:
            return 4;
    }
}
发布评论

评论列表(0)

  1. 暂无评论