javascript - D3JS : I'm not being able to iterate an array

标签 javascript d3.js

我正在尝试使用 D3JS 在几个图表下方附加一些文本(如标题)。为此,我尝试附加一个“g”元素并在其中添加一个“text”元素,然后尝试通过 jQuery 访问“text”元素数组以使用此路由设置 html:

$("#pie"+ i).find("text:nth-child(4)").eq(1) 

,它指向每个圆环图下方的“文本”,并使用 for 循环我试图将某些文本设置为存储在字符串数组中,但我无法遍历“文本”元素数组.你能告诉我我哪里错了吗?

这是我尝试过但没有成功的方法:

   g.append("text")
        .attr("transform", "translate(0,60) scale(.7)")
        .attr("class","caption")

    var captionArr = ["chart 1","chart 2","chart 3","chart 4","chart 5","chart 6","chart 7","chart 8"]    

    for(i = 1; i <= $(".caption").lenght; i++){
     ($("#pie"+ i).find("text:nth-child(4)").eq(1)).html(captionArr[i])
    }   

这是我的 fiddle :

http://jsfiddle.net/jcrr1985/q2uxs8r1/6/

感谢您的帮助,我非常感谢。

最佳答案

您的代码有两个主要问题:

  1. 主要问题是您要附加 text.caption<g>在导致 $('.caption').length === 16 的 SVG 中这不是我认为你需要的,因为你试图为每个图表添加 1 个标签(标题)。如果不是这种情况,请告诉我,我会编辑帖子。
  2. 您试图在绘制图表之前更改文本。所以你得移动fordraw 下方循环通话

    要修复上面的 #1,需要进行相关更改(附加到 svg 而不是 g ):

    svg.append("text")
      .attr("transform", "translate(0,60) scale(.7)")
      .attr("class", "caption");
    

使用 jQuery 的方法 1:

for (var i = 1; i <= $(".caption").length; i++) {
  $("#pie" + i).find("text.caption").html(newarr[i-1]); // as array index starts from 0
}

	var myGroup = '<g><path class="st0" d="M15.6,10.9c1.3,0,2.4-1.2,2.4-2.7c0-1.5-1.1-2.7-2.4-2.7c-1.3,0-2.4,1.2-2.4,2.7C13.2,9.7,14.2,10.9,15.6,10.9L15.6,10.9z"/><path class="st0" d="M18.6,11.6h-1.2l-1.8,5.5l-1.8-5.5h-1.2c-1.3,0-2.4,1.2-2.4,2.7v13h2.4l1.2,16.4h3.6l1.2-16.4H21v-13C21,12.8,19.9,11.6,18.6,11.6L18.6,11.6z"/><path class="st0" d="M31.9,10.9c1.3,0,2.4-1.2,2.4-2.7c0-1.5-1.1-2.7-2.4-2.7c-1.3,0-2.4,1.2-2.4,2.7C29.5,9.7,30.6,10.9,31.9,10.9L31.9,10.9z"/><path class="st0" d="M39.8,25.2l-3.6-11.6c0,0-0.6-2-2.4-2h-3.6c-1.8,0-2.4,2-2.4,2l-3.6,11.6l1.2,0.7l4.2-9.5l-3.6,14.3h3.6l1.2,13h2.4l1.2-13H38l-3.6-14.3l4.2,9.5L39.8,25.2L39.8,25.2z"/></g>';

	var data1 = [50, 50];
	var data2 = [70, 30];
	var data3 = [16, 84];
	var data4 = [12, 88];
	var data5 = [29, 71];
	var data6 = [15, 85];
	var data7 = [12, 88];
	var data8 = [10, 90];
	var newarr = ["chart 1", "chart 2", "chart 3", "chart 4", "chart 5", "chart 6", "chart 7", "chart 8"]

	var width = 150,
	  height = 150,
	  radius = (Math.min(width, height) / 2.8);

	function drawDonut(data, divchart) {
	  var sym = "%"

	  var color = ["#BC204B", "#00338D"];

	  // sort data
	  //data = data.sort(function (a, b) { return b-a; });
	  var pie = d3.pie()
	    .sortValues(null) // both null means NO sort
	    .value(function(d) {
	      return d
	    })(data);

	  var arc = d3.arc()
	    .outerRadius(radius - 10)
	    .innerRadius(radius - (radius / 1.9));

	  var labelArc = d3.arc()
	    .outerRadius(radius - 31)
	    .innerRadius(radius - 31);

	  var svg = d3.select(divchart)
	    .append("svg")
	    .attr("width", width)
	    .attr("height", height)
	    .append("g")
	    .attr("transform", "translate(" + 75 + "," + 75 + ")");

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


	  function easeInverse(ease) {
	    return function(e) {
	      var min = 0,
	        max = 1;
	      while (max - min > 1e-3) {
	        var mid = (max + min) * 0.5;
	        emid = ease(mid);
	        if (emid > e) {
	          max = mid;
	        } else {
	          min = mid;
	        }
	      }
	      return max;
	    }
	  }
	  var inverseCubic = easeInverse(d3.easeCubic);
	  var oneOver2Pi = 1.0 / (2 * Math.PI);
	  var total_msec = 2000;

	  g.append("path")
	    .style("fill", function(d, i) {
	      return color[i];
	    })
	    .transition()
	    .ease(d3.easeLinear)
	    .delay(function(d) {
	      return total_msec * inverseCubic(d.startAngle * oneOver2Pi);
	    })
	    .duration(function(d) {
	      return total_msec * (inverseCubic(d.endAngle * oneOver2Pi) - inverseCubic(d.startAngle * oneOver2Pi));
	    })
	    .attrTween("d", arcTween);

	  function arcTween(d) {
	    var i = d3.interpolate(inverseCubic(d.startAngle * oneOver2Pi), inverseCubic(d.endAngle * oneOver2Pi));
	    return function(t) {
	      d.endAngle = 2 * Math.PI * d3.easeCubic(i(t));
	      return arc(d);
	    }
	  }

	  g.append("g")
	    .attr("transform", "translate(-17,-17) scale(0.7)")
	    .html(myGroup);

	  g.append("text")
	    .attr("transform", "translate(-10,-55) scale(1)")
	    .attr("class", "st0")
	    .html(data[0] + "%");


	  svg.append("text")
	    .attr("transform", "translate(0,60) scale(.7)")
	    .attr("class", "caption");
	}


	drawDonut(data1, "#pie1")
	drawDonut(data2, "#pie2")
	drawDonut(data3, "#pie3")
	drawDonut(data4, "#pie4")
	drawDonut(data5, "#pie5")
	drawDonut(data6, "#pie6")
	drawDonut(data7, "#pie7")
	drawDonut(data8, "#pie8")

/* By the code below I'm trying to append some text below each chart, but something's wrong with it*/
	for (var i = 1; i <= $(".caption").length; i++) {
	  $("#pie" + i).find("text.caption").html(newarr[i-1]);
	}
        div {
          display: inline;
        }

        .st0 {
          fill: #00338D;
        }
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Donut man-woman</title>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
    <script src="https://d3js.org/d3.v5.min.js"></script>

    <body>
      <div id="pie1"></div>
      <div id="pie2"></div>
      <div id="pie3"></div>
      <div id="pie4"></div>
      <div id="pie5"></div>
      <div id="pie6"></div>
      <div id="pie7"></div>
      <div id="pie8"></div>
      <div id="pie9"></div>
    </body>

使用 d3 的方法 2 会在选择更新时出现困惑:

d3.selectAll('text.caption').text(function (d, i) { 
  return newarr[i];
});

	var myGroup = '<g><path class="st0" d="M15.6,10.9c1.3,0,2.4-1.2,2.4-2.7c0-1.5-1.1-2.7-2.4-2.7c-1.3,0-2.4,1.2-2.4,2.7C13.2,9.7,14.2,10.9,15.6,10.9L15.6,10.9z"/><path class="st0" d="M18.6,11.6h-1.2l-1.8,5.5l-1.8-5.5h-1.2c-1.3,0-2.4,1.2-2.4,2.7v13h2.4l1.2,16.4h3.6l1.2-16.4H21v-13C21,12.8,19.9,11.6,18.6,11.6L18.6,11.6z"/><path class="st0" d="M31.9,10.9c1.3,0,2.4-1.2,2.4-2.7c0-1.5-1.1-2.7-2.4-2.7c-1.3,0-2.4,1.2-2.4,2.7C29.5,9.7,30.6,10.9,31.9,10.9L31.9,10.9z"/><path class="st0" d="M39.8,25.2l-3.6-11.6c0,0-0.6-2-2.4-2h-3.6c-1.8,0-2.4,2-2.4,2l-3.6,11.6l1.2,0.7l4.2-9.5l-3.6,14.3h3.6l1.2,13h2.4l1.2-13H38l-3.6-14.3l4.2,9.5L39.8,25.2L39.8,25.2z"/></g>';

	var data1 = [50, 50];
	var data2 = [70, 30];
	var data3 = [16, 84];
	var data4 = [12, 88];
	var data5 = [29, 71];
	var data6 = [15, 85];
	var data7 = [12, 88];
	var data8 = [10, 90];
	var newarr = ["chart 1", "chart 2", "chart 3", "chart 4", "chart 5", "chart 6", "chart 7", "chart 8"]

	var width = 150,
	  height = 150,
	  radius = (Math.min(width, height) / 2.8);

	function drawDonut(data, divchart) {
	  var sym = "%"

	  var color = ["#BC204B", "#00338D"];

	  // sort data
	  //data = data.sort(function (a, b) { return b-a; });
	  var pie = d3.pie()
	    .sortValues(null) // both null means NO sort
	    .value(function(d) {
	      return d
	    })(data);

	  var arc = d3.arc()
	    .outerRadius(radius - 10)
	    .innerRadius(radius - (radius / 1.9));

	  var labelArc = d3.arc()
	    .outerRadius(radius - 31)
	    .innerRadius(radius - 31);

	  var svg = d3.select(divchart)
	    .append("svg")
	    .attr("width", width)
	    .attr("height", height)
	    .append("g")
	    .attr("transform", "translate(" + 75 + "," + 75 + ")");

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


	  function easeInverse(ease) {
	    return function(e) {
	      var min = 0,
	        max = 1;
	      while (max - min > 1e-3) {
	        var mid = (max + min) * 0.5;
	        emid = ease(mid);
	        if (emid > e) {
	          max = mid;
	        } else {
	          min = mid;
	        }
	      }
	      return max;
	    }
	  }
	  var inverseCubic = easeInverse(d3.easeCubic);
	  var oneOver2Pi = 1.0 / (2 * Math.PI);
	  var total_msec = 2000;

	  g.append("path")
	    .style("fill", function(d, i) {
	      return color[i];
	    })
	    .transition()
	    .ease(d3.easeLinear)
	    .delay(function(d) {
	      return total_msec * inverseCubic(d.startAngle * oneOver2Pi);
	    })
	    .duration(function(d) {
	      return total_msec * (inverseCubic(d.endAngle * oneOver2Pi) - inverseCubic(d.startAngle * oneOver2Pi));
	    })
	    .attrTween("d", arcTween);

	  function arcTween(d) {
	    var i = d3.interpolate(inverseCubic(d.startAngle * oneOver2Pi), inverseCubic(d.endAngle * oneOver2Pi));
	    return function(t) {
	      d.endAngle = 2 * Math.PI * d3.easeCubic(i(t));
	      return arc(d);
	    }
	  }

	  g.append("g")
	    .attr("transform", "translate(-17,-17) scale(0.7)")
	    .html(myGroup);

	  g.append("text")
	    .attr("transform", "translate(-10,-55) scale(1)")
	    .attr("class", "st0")
	    .html(data[0] + "%");


	  svg.append("text")
	    .attr("transform", "translate(0,60) scale(.7)")
	    .attr("class", "caption");
	}


	drawDonut(data1, "#pie1")
	drawDonut(data2, "#pie2")
	drawDonut(data3, "#pie3")
	drawDonut(data4, "#pie4")
	drawDonut(data5, "#pie5")
	drawDonut(data6, "#pie6")
	drawDonut(data7, "#pie7")
	drawDonut(data8, "#pie8")

  d3.selectAll('text.caption').text(function (d, i) { 
    return newarr[i];
  });
        div {
          display: inline;
        }

        .st0 {
          fill: #00338D;
        }
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Donut man-woman</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>

    <body>
      <div id="pie1"></div>
      <div id="pie2"></div>
      <div id="pie3"></div>
      <div id="pie4"></div>
      <div id="pie5"></div>
      <div id="pie6"></div>
      <div id="pie7"></div>
      <div id="pie8"></div>
      <div id="pie9"></div>
    </body>

更好的方法: 将参数或索引传递给 drawDonut .

将所有数据数组移动到名为 dataObj 的单个对象后, 调用 drawDonut以下方式:

Object.keys(dataObj).forEach(function (d, i) {
  drawDonut(dataObj[d], '#pie'+(i+1), i, 'chart ' + (i+1));
});

传递索引的地方以及作为第 4 个参数的图表名称(使用您认为方便的任何一个),文本将通过以下方式获取文本:

svg.append("text")
   .attr("transform", "translate(0,60) scale(.7)")
   .attr("class", "caption").text(chartName || newarr[index]);

	var myGroup = '<g><path class="st0" d="M15.6,10.9c1.3,0,2.4-1.2,2.4-2.7c0-1.5-1.1-2.7-2.4-2.7c-1.3,0-2.4,1.2-2.4,2.7C13.2,9.7,14.2,10.9,15.6,10.9L15.6,10.9z"/><path class="st0" d="M18.6,11.6h-1.2l-1.8,5.5l-1.8-5.5h-1.2c-1.3,0-2.4,1.2-2.4,2.7v13h2.4l1.2,16.4h3.6l1.2-16.4H21v-13C21,12.8,19.9,11.6,18.6,11.6L18.6,11.6z"/><path class="st0" d="M31.9,10.9c1.3,0,2.4-1.2,2.4-2.7c0-1.5-1.1-2.7-2.4-2.7c-1.3,0-2.4,1.2-2.4,2.7C29.5,9.7,30.6,10.9,31.9,10.9L31.9,10.9z"/><path class="st0" d="M39.8,25.2l-3.6-11.6c0,0-0.6-2-2.4-2h-3.6c-1.8,0-2.4,2-2.4,2l-3.6,11.6l1.2,0.7l4.2-9.5l-3.6,14.3h3.6l1.2,13h2.4l1.2-13H38l-3.6-14.3l4.2,9.5L39.8,25.2L39.8,25.2z"/></g>';

	var dataObj = {
  	data1: [50, 50],
		data2: [70, 30],
		data3: [16, 84],
		data4: [12, 88],
		data5: [29, 71],
		data6: [15, 85],
		data7: [12, 88],
		data8: [10, 90]
  };  
	var newarr = ["chart 1", "chart 2", "chart 3", "chart 4", "chart 5", "chart 6", "chart 7", "chart 8"]

	var width = 150,
	  height = 150,
	  radius = (Math.min(width, height) / 2.8);

	function drawDonut(data, divchart, index, chartName) {
	  var sym = "%"

	  var color = ["#BC204B", "#00338D"];

	  // sort data
	  //data = data.sort(function (a, b) { return b-a; });
	  var pie = d3.pie()
	    .sortValues(null) // both null means NO sort
	    .value(function(d) {
	      return d
	    })(data);

	  var arc = d3.arc()
	    .outerRadius(radius - 10)
	    .innerRadius(radius - (radius / 1.9));

	  var labelArc = d3.arc()
	    .outerRadius(radius - 31)
	    .innerRadius(radius - 31);

	  var svg = d3.select(divchart)
	    .append("svg")
	    .attr("width", width)
	    .attr("height", height)
	    .append("g")
	    .attr("transform", "translate(" + 75 + "," + 75 + ")");

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


	  function easeInverse(ease) {
	    return function(e) {
	      var min = 0,
	        max = 1;
	      while (max - min > 1e-3) {
	        var mid = (max + min) * 0.5;
	        emid = ease(mid);
	        if (emid > e) {
	          max = mid;
	        } else {
	          min = mid;
	        }
	      }
	      return max;
	    }
	  }
	  var inverseCubic = easeInverse(d3.easeCubic);
	  var oneOver2Pi = 1.0 / (2 * Math.PI);
	  var total_msec = 2000;

	  g.append("path")
	    .style("fill", function(d, i) {
	      return color[i];
	    })
	    .transition()
	    .ease(d3.easeLinear)
	    .delay(function(d) {
	      return total_msec * inverseCubic(d.startAngle * oneOver2Pi);
	    })
	    .duration(function(d) {
	      return total_msec * (inverseCubic(d.endAngle * oneOver2Pi) - inverseCubic(d.startAngle * oneOver2Pi));
	    })
	    .attrTween("d", arcTween);

	  function arcTween(d) {
	    var i = d3.interpolate(inverseCubic(d.startAngle * oneOver2Pi), inverseCubic(d.endAngle * oneOver2Pi));
	    return function(t) {
	      d.endAngle = 2 * Math.PI * d3.easeCubic(i(t));
	      return arc(d);
	    }
	  }

	  g.append("g")
	    .attr("transform", "translate(-17,-17) scale(0.7)")
	    .html(myGroup);

	  g.append("text")
	    .attr("transform", "translate(-10,-55) scale(1)")
	    .attr("class", "st0")
	    .html(data[0] + "%");


	  svg.append("text")
	    .attr("transform", "translate(0,60) scale(.7)")
	    .attr("class", "caption").text(chartName || newarr[index]);
	}


	Object.keys(dataObj).forEach(function (d, i) {
  	drawDonut(dataObj[d], '#pie'+(i+1), i, 'chart ' + (i+1));
  });
        div {
          display: inline;
        }

        .st0 {
          fill: #00338D;
        }
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Donut man-woman</title>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
    <script src="https://d3js.org/d3.v5.min.js"></script>

    <body>
      <div id="pie1"></div>
      <div id="pie2"></div>
      <div id="pie3"></div>
      <div id="pie4"></div>
      <div id="pie5"></div>
      <div id="pie6"></div>
      <div id="pie7"></div>
      <div id="pie8"></div>
      <div id="pie9"></div>
    </body>

还有其他方法,但我认为其中一种可能暂时对您有所帮助。希望这会有所帮助。

关于javascript - D3JS : I'm not being able to iterate an array,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51951377/

相关文章:

javascript - 将 zclip 分配给隐藏 div 中的多个链接时出现问题

javascript - 沿多条路径动画圆圈

javascript - 如何获取一组生成的 D3.js 元素中每个元素的高度?

javascript - 如何在图例中设置符号?

javascript - 将变量传递给 Handlebars 上的每个响应

javascript - 将数组从 javascript 传递到 WordPress 中的页面

javascript - Nodejs - 抛出不可预知的错误,因为 `property ' get' of undefined`

javascript - 用谷歌脚本中的条件替换字符串

javascript - d3.js 逆气泡图

javascript - d3js 阻止 forceSimulation 一直重新计算位置