D3JS:我无法迭代数组

时间:2018-08-21 14:50:15

标签: 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])
    }   

这是我的小提琴:

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

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

2 个答案:

答案 0 :(得分:1)

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

  1. 主要问题是您要将SVG中的每个text.caption附加到<g>上,从而导致$('.caption').length === 16并不是我想添加时所需要的每个图表1个标签(标题)。如果不是这种情况,请告诉我,我将对其进行编辑。
  2. 您正在尝试在绘制图表之前更改文本。因此,您必须将for调用下面的draw循环

    要修复上面的#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));
});

传递索引的地方,还有chartName作为第四个参数(使用您觉得方便的那个),文本将通过以下方式获取文本:

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>

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

答案 1 :(得分:0)

为什么不这么做:

phpinfo()