d3.js: групповые аккорды на диаграмме одним цветом

1

Моя цель - сгруппировать аккорды с помощью одного цвета, подобного этому (здесь он красный, серый, синий): Изображение 174551

Я подумал о чем-то вроде этого:

var groups = [
        {sIndex: 0, eIndex: 1, title: 'Group1', color: '#004F9F'},
        {sIndex: 2, eIndex: 5, title: 'Group2', color: '#df7c00'},
        {sIndex: 6, eIndex: 7, title: 'Group3', color: '#0D57A6'},
        {sIndex: 8, eIndex: 9, title: 'Group4', color: '#008A34'}
    ];

sIndex & eIndex определяет начало и конец каждой группы. Однако я не знаю, как правильно его закодировать.

Здесь весь мой код:

d3.csv("description.csv", function(d) {
	return d;
}, draw);

function draw(description) {

	////////////////////////////////////////////////////////////
	//////////////////////// Set-Up ////////////////////////////
	////////////////////////////////////////////////////////////

	var margin = {left:90, top:90, right:90, bottom:90},
			width = Math.min(window.innerWidth, 1000) - margin.left - margin.right,
	    height = Math.min(window.innerWidth, 1000) - margin.top - margin.bottom,
	    innerRadius = Math.min(width, height) * .39,
	    outerRadius = innerRadius * 1.1;

	var names = [ "Site1", "Site2",
								"YouTube","Twitter", "Google+", "Instagram",
								"App1", "App2",
								"Content1", "Content2" ],
      colors = ["#301E1E", "#083E77", "#342350", "#567235", "#8B161C", "#DF7C00"],
      opacityDefault = 0.8;

			var matrix = [
	      [0,1,1,1,1,1,1,1,1,1],
	      [0,0,1,1,1,1,1,0,1,1],
	      [0,1,0,0,0,0,0,0,0,1],
	      [0,1,1,0,1,1,0,1,1,1],
	      [0,1,1,1,0,1,1,1,1,1],
	      [0,1,1,1,1,0,1,1,1,1],
	      [0,1,1,1,1,1,0,1,1,1],
	      [0,0,0,0,0,0,1,0,1,1],
	      [0,0,0,0,0,0,1,0,1,0],
	      [0,1,1,1,1,1,1,0,0,1]
	    ];

	//define grouping with colors
	var groups = [
		{sIndex: 0, eIndex: 1, title: 'Group1', color: '#004F9F'},
		{sIndex: 2, eIndex: 5, title: 'Group2', color: '#df7c00'},
		{sIndex: 6, eIndex: 7, title: 'Group3', color: '#0D57A6'},
		{sIndex: 8, eIndex: 9, title: 'Group4', color: '#008A34'}
	];

	////////////////////////////////////////////////////////////
	/////////// Create scale and layout functions //////////////
	////////////////////////////////////////////////////////////

	var colors = d3.scaleOrdinal()
	    .domain(d3.range(names.length))
			.range(colors);

	var chord = d3.chord()
	    .padAngle(.15)
	    .sortChords(d3.descending);

	var arc = d3.arc()
	    .innerRadius(innerRadius*1.01)
	    .outerRadius(outerRadius);

	var path = d3.ribbon()
			.radius(innerRadius);


	var svg = d3.select("#chart").append("svg")
	    .attr("width", width + margin.left + margin.right)
	    .attr("height", height + margin.top + margin.bottom)
			.append("g")
	    .attr("transform", "translate(" + (width/2 + margin.left) + "," + (height/2 + margin.top) + ")")
			.datum(chord(matrix));

	////////////////////////////////////////////////////////////
	////////////////// Draw outer Arcs /////////////////////////
	////////////////////////////////////////////////////////////

	var outerArcs = svg.selectAll("g.group")
		.data(function(chu) { return chu.groups; })
		.enter().append("g")
		.attr("class", "group")
		.on("mouseover", fade(.1))
		.on("mouseout", fade(opacityDefault))

	outerArcs.append("path")
		.style("fill", function(d) {return colors(d.index); })
		.attr("d", arc);

	////////////////////////////////////////////////////////////
	////////////////////// Append names ////////////////////////
	////////////////////////////////////////////////////////////

	//Append the label names on the outside
	outerArcs.append("text")
	  .each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; })
	  .attr("dy", ".35em")
	  .attr("class", "titles")
	  .attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
	  .attr("transform", function(d) {
			return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
			+ "translate(" + (outerRadius + 10) + ")"
			+ (d.angle > Math.PI ? "rotate(180)" : "");
	  })
	  .text(function(d,i) { return names[i]; });

	////////////////////////////////////////////////////////////
	////////////////// Draw inner chords ///////////////////////
	////////////////////////////////////////////////////////////

	svg.selectAll("path.chord")
		.data(function(chords) { return chords; })
		.enter().append("path")
		.attr("class", "chord")
		.style("fill", function(d) { return colors(d.source.index); })
		.style("opacity", opacityDefault)
		.attr("d", path);

	////////////////////////////////////////////////////////////
	////////////////// Extra Functions /////////////////////////
	////////////////////////////////////////////////////////////

	//Returns an event handler for fading a given chord group.
	function fade(opacity) {
	  return function(d,i) {
	    svg.selectAll("path.chord")
	        .filter(function(d) { return d.source.index != i && d.target.index != i; })
			.transition()
	        .style("opacity", opacity);
	  };
	}//fade
}
<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>Testing</title>

		<!-- D3.js & tool-tip -->
		<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>

		<!-- Google Fonts -->
		<link href='https://fonts.googleapis.com/css?family=Lato:400,900' rel='stylesheet' type='text/css'>

		<style>
			body {
			  font-size: 12px;
			  font-family: 'Lato', sans-serif;
			  text-align: center;
			  fill: #2B2B2B;
			  cursor: default;
			}

			@media (min-width: 600px) {
				#chart{
					font-size: 14px;
				}
			}
		</style>
	</head>
	<body>

		<div id = "chart"></div>
		<script src = "script.js"></script>

  </body>
</html>
Теги:
d3.js
svg

1 ответ

2
Лучший ответ

Вы можете отфильтровать массив groups чтобы получить цвет:

.style("fill", function(d) {
    var thisGroup = groups.filter(function(e) {
        return e.sIndex === d.index || e.eIndex === d.index;
    });
    return thisGroup[0] ? thisGroup[0].color : "gray";
})

Вот ваш код:

draw();

function draw(description) {

  ////////////////////////////////////////////////////////////
  //////////////////////// Set-Up ////////////////////////////
  ////////////////////////////////////////////////////////////

  var margin = {
      left: 90,
      top: 90,
      right: 90,
      bottom: 90
    },
    width = Math.min(window.innerWidth, 1000) - margin.left - margin.right,
    height = Math.min(window.innerWidth, 1000) - margin.top - margin.bottom,
    innerRadius = Math.min(width, height) * .39,
    outerRadius = innerRadius * 1.1;

  var names = ["Site1", "Site2",
      "YouTube", "Twitter", "Google+", "Instagram",
      "App1", "App2",
      "Content1", "Content2"
    ],
    colors = ["#301E1E", "#083E77", "#342350", "#567235", "#8B161C", "#DF7C00"],
    opacityDefault = 0.8;

  var matrix = [
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [0, 0, 1, 1, 1, 1, 1, 0, 1, 1],
    [0, 1, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 1, 1, 0, 1, 1, 0, 1, 1, 1],
    [0, 1, 1, 1, 0, 1, 1, 1, 1, 1],
    [0, 1, 1, 1, 1, 0, 1, 1, 1, 1],
    [0, 1, 1, 1, 1, 1, 0, 1, 1, 1],
    [0, 0, 0, 0, 0, 0, 1, 0, 1, 1],
    [0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
    [0, 1, 1, 1, 1, 1, 1, 0, 0, 1]
  ];

  //define grouping with colors
  var groups = [{
    sIndex: 0,
    eIndex: 1,
    title: 'Group1',
    color: '#004F9F'
  }, {
    sIndex: 2,
    eIndex: 5,
    title: 'Group2',
    color: '#df7c00'
  }, {
    sIndex: 6,
    eIndex: 7,
    title: 'Group3',
    color: '#0D57A6'
  }, {
    sIndex: 8,
    eIndex: 9,
    title: 'Group4',
    color: '#008A34'
  }];

  ////////////////////////////////////////////////////////////
  /////////// Create scale and layout functions //////////////
  ////////////////////////////////////////////////////////////

  var colors = d3.scaleOrdinal()
    .domain(d3.range(names.length))
    .range(colors);

  var chord = d3.chord()
    .padAngle(.15)
    .sortChords(d3.descending);

  var arc = d3.arc()
    .innerRadius(innerRadius * 1.01)
    .outerRadius(outerRadius);

  var path = d3.ribbon()
    .radius(innerRadius);


  var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + (width / 2 + margin.left) + "," + (height / 2 + margin.top) + ")")
    .datum(chord(matrix));

  ////////////////////////////////////////////////////////////
  ////////////////// Draw outer Arcs /////////////////////////
  ////////////////////////////////////////////////////////////

  var outerArcs = svg.selectAll("g.group")
    .data(function(chu) {
      return chu.groups;
    })
    .enter().append("g")
    .attr("class", "group")
    .on("mouseover", fade(.1))
    .on("mouseout", fade(opacityDefault))

  outerArcs.append("path")
    .style("fill", function(d) {
      var thisGroup = groups.filter(function(e) {
        return e.sIndex === d.index || e.eIndex === d.index;
      });
      return thisGroup[0] ? thisGroup[0].color : "gray";
    })
    .attr("d", arc);

  ////////////////////////////////////////////////////////////
  ////////////////////// Append names ////////////////////////
  ////////////////////////////////////////////////////////////

  //Append the label names on the outside
  outerArcs.append("text")
    .each(function(d) {
      d.angle = (d.startAngle + d.endAngle) / 2;
    })
    .attr("dy", ".35em")
    .attr("class", "titles")
    .attr("text-anchor", function(d) {
      return d.angle > Math.PI ? "end" : null;
    })
    .attr("transform", function(d) {
      return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" + "translate(" + (outerRadius + 10) + ")" + (d.angle > Math.PI ? "rotate(180)" : "");
    })
    .text(function(d, i) {
      return names[i];
    });

  ////////////////////////////////////////////////////////////
  ////////////////// Draw inner chords ///////////////////////
  ////////////////////////////////////////////////////////////

  svg.selectAll("path.chord")
    .data(function(chords) {
      return chords;
    })
    .enter().append("path")
    .attr("class", "chord")
    .style("fill", function(d) {
      var thisGroup = groups.filter(function(e) {
        return e.sIndex == d.source.index || e.eIndex == d.source.index;
      });
      return thisGroup[0] ? thisGroup[0].color : "gray";
    })
    .style("opacity", opacityDefault)
    .attr("d", path);

  ////////////////////////////////////////////////////////////
  ////////////////// Extra Functions /////////////////////////
  ////////////////////////////////////////////////////////////

  //Returns an event handler for fading a given chord group.
  function fade(opacity) {
    return function(d, i) {
      svg.selectAll("path.chord")
        .filter(function(d) {
          return d.source.index != i && d.target.index != i;
        })
        .transition()
        .style("opacity", opacity);
    };
  } //fade
}
<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>Testing</title>

		<!-- D3.js & tool-tip -->
		<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>

		<!-- Google Fonts -->
		<link href='https://fonts.googleapis.com/css?family=Lato:400,900' rel='stylesheet' type='text/css'>

		<style>
			body {
			  font-size: 12px;
			  font-family: 'Lato', sans-serif;
			  text-align: center;
			  fill: #2B2B2B;
			  cursor: default;
			}

			@media (min-width: 600px) {
				#chart{
					font-size: 14px;
				}
			}
		</style>
	</head>
	<body>

		<div id = "chart"></div>
		<script src = "script.js"></script>

  </body>
</html>

PS: У вас есть некоторые проблемы с этими индексами, поэтому я написал тройную функцию, чтобы вернуть "серый", если отфильтрованное значение не undefined.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню