# d3arc圆弧生成器

# d3.arc 和d3.pie画圆环图和饼图

api 作用 例子
d3.arc() 生成一个弧。 您需要为弧设置内半径和外半径。 如果内半径为0,则结果将为饼图,否则结果将为圆环图 d3.arc().outerRadius(radius - 10).innerRadius(0)
d3.pie() 生成饼图。 它从数据集中获取数据并计算饼图的每个楔形的起始角度和结束角度。 (如果后台给的数据已经符合arc要求就可以不使用了)
  • innerRadius(0) 内圈半径
  • outerRadius(200) 外圈半径
  • cornerRadius(20) 拐角半径
  • padAngle() 组成圆弧之间的空隙,弧度制
var arc = d3.arc().innerRadius(0).outerRadius(200).cornerRadius(20).padAngle(0.01); 
  • 控制文字在弧形上的位置
 var centroid = arc.centroid(d);
let drawData = d3
             .pie()
             .value(function(d) {
               return d.y
             })
             .sort(null)//用来排序使用如(d=>d.id)根据id来排序
             .sortValues(null)
             .startAngle(0)
             .endAngle(Math.PI * 2)
             .padAngle(0.05)(oriData)
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>d3 pie</title>
 
</head>
<body>
<div id="chart"></div>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script type="text/javascript">
var color=[
"POWDERBLUE","AQUAMARINE","LIMEGREEN","SEASHELL","MEDIUMPURPLE","LIGHTGOLDENRODYELLOW","LAVENDERBLUSH","skyblue"];
 
var svg=d3.select("#chart")
	.append("svg")
	.attr("width",400) 
	.attr("height",400)
 
	var g=svg.append("g")
	.attr("transform","translate(200,200)")
var data = [1, 1, 2, 3, 5, 8, 13, 21];
var arcs = d3.pie()(data);
// console.log(arcs)
var arc = d3.arc().innerRadius(20).outerRadius(200).cornerRadius(20).padAngle(0.01);
 
g.selectAll("path")
	.data(arcs)
	.enter()
	.append("path")
	.attr("d",arc)
	.style("fill",function(d,i){return color[i%8];})
d3.select('g')
    .selectAll('text')
    .data(arcs)
    .enter()
    .append('text')
    .each(function(d) {
		console.log(d);
       var centroid = arc.centroid(d);
        d3.select(this)
            .attr('x', centroid[0])
            .attr('y', centroid[1])
            .attr('dy', '0.33em')
            .text(d.data)
			.style("fill","#001");
    });
 
</script>
</body>
</html>
</html>
states,percent
UP,80.00
Maharastra,70.00
Bihar,65.0
MP,60.00
Gujarat,50.0
WB,49.0
TN,35.0
<!DOCTYPE html>
<html>
   <head>
      <style>
         .arc text {
            font: 12px arial;
            text-anchor: middle;
         }
         
         .arc path {
            stroke: #fff;
         }
        
        .title {
            fill: green;
            font-weight: italic;
         }
      </style>
      
      <script type = "text/javascript" src = "https://d3js.org/d3.v6.min.js"></script>
   </head>

   <body>
      <svg width = "400" height = "400"></svg>
      <script>
         var svg = d3.select("svg"),
            width = svg.attr("width"),
            height = svg.attr("height"),
            radius = Math.min(width, height) / 2;
        
         var g = svg.append("g")
            .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

         var color = d3.scaleOrdinal([
            'gray', 'green', 'brown', 'orange', 'yellow', 'red', 'purple'
         ]);
         
         var pie = d3.pie().value(function(d) { 
            return d.percent; 
         });
         
         var path = d3.arc()
            .outerRadius(radius - 10).innerRadius(0);
        
         var label = d3.arc()
            .outerRadius(radius).innerRadius(radius - 80);
         
         d3.csv("1.csv").then(data=>{
			 
			 var arc = g.selectAll(".arc")
			    .data(pie(data))
			    .enter()
			    .append("g")
			    .attr("class", "arc");
			 
			 arc.append("path")
			    .attr("d", path)
			    .attr("fill", function(d) { return color(d.data.states); });
			         
			 console.log(arc)
			         
			 arc.append("text").attr("transform", function(d) { 
			    return "translate(" + label.centroid(d) + ")"; 
			 })
			 
			 .text(function(d) { return d.data.states; });
		 })
         
         svg.append("g")
            .attr("transform", "translate(" + (width / 2 - 120) + "," + 20 + ")")
            .append("text").text("Top population states in india")
            .attr("class", "title")
      </script>
   </body>
</html>
// var data2 = [
           //     {startAngle: 0, endAngle: 0.1 * endAngle},
           //     {startAngle: 0.1 * endAngle, endAngle: 0.2 * endAngle},
           //     {startAngle: 0.2 * endAngle, endAngle: 0.4 * endAngle},
           //     {startAngle: 0.4 * endAngle, endAngle: 0.6 * endAngle},
           //     {startAngle: 0.6 * endAngle, endAngle: 0.7 * endAngle},
           //     {startAngle: 0.7 * endAngle, endAngle: 0.9 * endAngle},
           //     {startAngle: 0.9 * endAngle, endAngle: endAngle}
           // ];
		   
var data1=[0.1,0.2,0.4,0.6,0.7,0.9,1]
//data1通过d3.pie转换成data2,如果提供的数据就是data2就可以直接使用而不需要d3.pie()进行转换
  • 关键帧和插值器集合使用
 
   <!DOCTYPE html>
   <html>
   <head>
       <meta charset="utf-8">
       <title>Arc Transition</title>
       <style type="text/css">
       	*{
			margin:0;
			padding:0
		}
       </style>
       <script type = "text/javascript" src = "https://d3js.org/d3.v6.min.js"></script>
   </head>
   
   <body>
   <div>
     <svg id='svg6'/>
   </div>
   <script type="text/javascript">
       const oriData = [
             { 'x': 'A计划', 'y': 20 },
             { 'x': 'B计划', 'y': 40 },
             { 'x': 'C计划', 'y': 90 },
             { 'x': 'D计划', 'y': 80 },
             { 'x': 'E计划', 'y': 120 },
             { 'x': 'F计划', 'y': 100 },
             { 'x': 'G计划', 'y': 60 }
           ];
           const [width, height] = [750, 350];
       
           let svg = d3.select('#svg6')
             .attr('width', width)
             .attr('height', height)
       
           let g = svg.append('g')
             .attr('transform', 'translate( 140, 40 )')
       
           //设置饼图的半径
           let radius = Math.min(width, height) * 0.8 / 2
       
           let arc = d3.arc()
             .innerRadius(70)
             // .outerRadius(radius)
             .cornerRadius(10)
       
           //饼图与文字相连的曲线起点
           let pointStart = d3.arc()
             .innerRadius(radius)
             .outerRadius(radius)
           //饼图与文字相连的曲线终点
           let pointEnd = d3.arc()
             .innerRadius(radius + 20)
             .outerRadius(radius + 20)
       
           let drawData = d3
             .pie()
             .value(function(d) {
               return d.y
             })
             .sort(null)
             .sortValues(null)
             .startAngle(0)
             .endAngle(Math.PI * 2)
             .padAngle(0.05)(oriData)
           console.log(drawData)
       
           let colorScale = d3
             .scaleOrdinal()
             .domain(d3.range(0, oriData.length))
             .range(d3.schemeSet1);
           g.append('g')
             .attr('transform', 'translate( ' + radius + ', ' + radius + ' )')
             .attr('stroke', 'steelblue')
             .attr('stroke-width', 1)
             .selectAll('path')
             .data(drawData)
             .enter()
             .append('path')
             .attr('fill', function(d) {
               return colorScale(d.index)
             })
             .attr('d', function(d) {
               d.outerRadius = radius;
               return arc(d)
             })
             .on('mouseover', arcTween(radius + 20, 0))
             .on('mouseout', arcTween(radius, 150))
             .transition()
             .duration(2000)
             .attrTween('d', function (d) {
             //初始加载时的过渡效果
               let fn = d3.interpolate({
                 endAngle: d.startAngle
               }, d)
               return function(t) {
                 return arc(fn(t))
               }
             })
       
           function arcTween(outerRadius, delay) {
             // 设置缓动函数,为鼠标事件使用
             return function() {
               d3.select(this)
                 .transition()
                 .delay(delay)
                 .attrTween('d', function(d) {
                   let i = d3.interpolate(d.outerRadius, outerRadius)
                   return function(t) {
                     d.outerRadius = i(t)
                     return arc(d)
                   }
                 })
             }
           }
       
           //文字层
           let sum = d3.sum(oriData, d => d.y);
           svg.append('g')
             .attr('transform', 'translate( ' + radius + ', ' + radius + ' )')
             .selectAll('text')
             .data(drawData)
             .enter()
             .append('text')
             .attr('transform', function(d) {
             // arc.centroid(d)将文字平移到弧的中心
               return 'translate(' + arc.centroid(d) + ') ' +
                 //rotate 使文字旋转扇形夹角一半的位置(也可不旋转)
                 'rotate(' + (-90 + (d.startAngle + (d.endAngle - d.startAngle)/2) * 180 / Math.PI) + ')'
             })
       			//文字开始点在文字中间
             .attr('text-anchor', 'middle')
       			//文字垂直居中
             .attr('dominant-baseline', 'central')
             .attr('font-size', '10px')
       			//格式化文字显示格式
             .text(function(d) {
               return (d.data.y / sum * 100).toFixed(2) + '%';
             })
			 
             // .attr('rotate', '30') //此设置为设置每个文字中字符的旋转,上面的旋转是以文字为一个整体的旋转
       
           //图例legend
           let legend = g.append('g')
             .attr('transform', 'translate( ' + radius * 2.5 + ', 0 )')
             .selectAll('g')
             .data(drawData)
             .enter()
             .append('g')
             .attr('transform', function(d, i) {
               return 'translate(0,' + i * 20 + ')'
             });
       
           legend
             .append('rect')
             .attr('width', 27)
             .attr('height', 18)
             .attr('fill', function(d) {
               return colorScale(d.index)
             });
           legend
             .append('text')
             .text(function(d) {
               return d.data.x
             })
             .style('font-size', 10)
             .attr('y', '1em')
             .attr('x', '3em')
             .attr('dy', 3)
       
           //曲线层
           g.append('g')
             .attr('transform', 'translate( ' + radius + ', ' + radius + ' )')
             .selectAll('path')
             .data(drawData)
             .enter()
             .append('path')
             .attr('d',
               d3
                 .linkHorizontal()
                 .source(function(d) {
                   return pointStart.centroid(d)
                 })
                 .target(function(d) {
                   return pointEnd.centroid(d)
                 })
             )
             .style('stroke', '#999')
             .style('stroke-width', 1)
             .attr('fill', 'none')
       
           //饼图外面的文字
           g.append('g')
             .attr('transform', 'translate( ' + radius + ', ' + radius + ' )')
             .selectAll('path')
             .data(drawData)
             .enter()
             .append('text')
             .text(function(d) {
               return d.data.x
             })
             .attr('x', function(d) {
               return pointEnd.centroid(d)[0]
             })
             .attr('y', function(d) {
               return pointEnd.centroid(d)[1]
             })
             .style('font-size', 10)
             .attr('text-anchor', function(d) {
               if (d.startAngle > Math.PI) {
                 return 'end'
               }
             })
             .attr('dominant-baseline', function(d) {
               if (d.index === 4) {
                 return 'hanging'
               }
             })
   </script>
   
   
   </body>
   
   </html>

# 环形图展开方式

  1. 每个弧自行展开
  2. 从12点方向全部展开
 .attrTween('d', function (d) {
       //初始加载时的过渡效果
	   let fn = d3.interpolate({
		 endAngle: d.startAngle
	   }, d)
	   return function(t) {
		 return arc(fn(t))
	   }
})
=========================================================
 .attrTween('d', function (d) {
	   var start = {startAngle: 0, endAngle: 0}; // <-A
	   var interpolate = d3.interpolate(start, d); // <-B					  
	   return function (t) {
		   return arc(interpolate(t)); // <-C
	   };
	 })
最后更新: 2/25/2021, 4:50:50 PM