【问题标题】:How would I create my own color scale based on the id of my data in d3?如何根据 d3 中数据的 id 创建自己的色标?
【发布时间】:2021-07-24 03:53:51
【问题描述】:

我正在尝试根据我的数据集的 ID 添加自定义色阶。我希望每个大陆都有自己的颜色。目前色阶由

设置
var fill = d3.scale.category20(); 

还有代码,

n.append("circle")
              .attr("r",  function(d) { return d.r; })
              .style("fill", function(d) { return fill(d.id); })

根据上述色标设置颜色。我正在尝试根据数据的 ID 使用自己的十六进制代码创建自己的色标。我该怎么做?我试图将 ID 更改为类别,但它弄乱了我的动画。如果你想自己玩代码,这里是 CodePen 上的代码链接:(https://codepen.io/jaswar1/pen/QWdRVXp)

  var data = [
      //Americas
      {"id": "0", "name": "U.S.A", "r": 62.20, "value": 22.20 },
      {"id": "0", "name": "Brazil", "r": 42.06, "value": 2.06 },
      {"id": "0", "name": "Canada", "r": 41.83, "value" :1.83 },
      {"id": "0", "name": "Mexico", "r": 41.3, "value": 1.30 },
      {"id": "0", "name": "Argentina", "r": 40.52, "value": 0.52 },
      
      //Asia
      {"id": "1", "name": "China", "r": 55.47, "value": 15.47 },
      {"id": "1", "name": "Japan", "r": 45.50, "value": 5.50 },
      {"id": "1", "name": "India", "r": 43.26, "value": 3.26 },
      {"id": "1", "name": "South Korea", "r": 41.74, "value": 1.74 },
      {"id": "1", "name": "Russia", "r": 41.67, "value": 1.67 },
      {"id": "1", "name": "Indonesia", "r": 41.21, "value": 1.21},
      {"id": "1", "name": "Turkey", "r": 40.81, "value": 0.81 },
    
      //Europe
      {"id": "2", "name": "Germany", "r": 44.16, "value": 4.16 },
      {"id": "2", "name": "United Kingdom", "r": 42.93, "value": 2.93},
      {"id": "2", "name": "Italy", "r": 42.09, "value": 2.09 },
      {"id": "2", "name": "Spain", "r": 41.50, "value": 1.50 },
      {"id": "2", "name": "Netherlands", "r": 40.95, "value": 0.95 },
      {"id": "2", "name": "Switzerland", "r": 40.74, "value": 0.74 },
      
      //Oceania
      {"id": "3", "name": "Australia", "r": 41.48, "value": 1.48 },
      {"id": "3", "name": "New Zealand", "r": 40.207, "value": 0.207 },
      
      //Africa 
      {"id": "4", "name": "Saudi Arabia", "r": 40.79, "value": 0.79},
      {"id": "4", "name": "South Africa", "r": 40.351, "value": 0.351},
      
    ];
    
    var width = window.innerWidth,
        height = 550;
    
    var fill = d3.scale.category20();
            
    
    var nodes = [], labels = [],
        foci = [{x: -100, y: 150}, {x: 350, y: 150}, {x: 200, y: 150}, {x: 400, y: 150}, {x: 500, y: 150}];
    
    var svg = d3.select("body").append("svg")
        .attr("width", "100%")
        .attr("height", height)
    
    var force = d3.layout.force()
        .nodes(nodes)
        .links([])
        .charge(-400)
    
        .gravity(0.1)
        .friction(0.9)
        .size([width, height])
        .on("tick", tick);
    
    var node = svg.selectAll("g");
    
    var counter = 0;
    
    function tick(e) {
      var k = .1 * e.alpha;
    
      // Push nodes toward their designated focus.
      nodes.forEach(function(o, i) {
        o.y += (foci[o.id].y - o.y) * k;
        o.x += (foci[o.id].x - o.x) * k;
      });
    
      node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
    
    }
    
    
    var timer = setInterval(function(){
    
      if (nodes.length > data.length-1) { clearInterval(timer); return;}
    
      var item = data[counter];
      nodes.push({id: item.id, r: item.r, name: item.name});
      force.start();
    
      node = node.data(nodes);
    
      var n = node.enter().append("g")
          .attr("class", "node")
          .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
          .style('cursor', 'pointer')
          .on('mousedown', function() {
             var sel = d3.select(this);
             sel.moveToFront();
          })
          .call(force.drag);
    
      n.append("circle")
          .attr("r",  function(d) { return d.r; })
          .style("fill", function(d) { return fill(d.id); })
    
      n.append("text")
          .text(function(d){
              return d.name
              return d.value;
          })
          .style("font-size", function(d) {
              return Math.min(1 * d.r, (1 * d.r - 8) / this.getComputedTextLength() * 16) + "px"; 
           })
          .attr("dy", ".2em")
    
      counter++;
    }, 100);
    
    
    d3.selection.prototype.moveToFront = function() {
      return this.each(function(){
        this.parentNode.appendChild(this);
      });
    };
    
    function resize() {
      width = window.innerWidth;
      force.size([width, height]);
      force.start();
    }
    
    d3.select(window).on('resize', resize)

【问题讨论】:

  • 尝试使用d3.scale.ordinal()函数的范围和域:var fill = d3.scale.ordinal() .domain([0,4]) .range(["#3182bd", "#9ecae1", "#fd8d3c", "#fdae6b", "#31a354"]);

标签: javascript d3.js colors data-visualization visualization


【解决方案1】:

有几种方法可以做到这一点:

  1. 将第 39 行 var fill = d3.scale.category20(); 替换为:
var fill = new Map([
  [0, '#3182bd'],
  [1, '#9ecae1'],
  [2, '#fd8d3c'],
  [3, '#fdae6b'],
  [4, '#31a354']
]);

和第 98 行 fill(d.id) 有了这个(显示第 96-98 行):

  n.append("circle")
      .attr("r",  function(d) { return d.r; })
      .style("fill", function(d) { return fill.get(d.id); })

(您也可以使用对象文字 var fill = {...} 或数组 var fill = [...] 并使用 fill[d.id] 访问它)

https://codepen.io/Alexander9111/pen/rNjEKEP

  1. 您可以编写一个新的填充函数:
var fill = (id) => {
  const arr = [
    '#3182bd',
    '#9ecae1',
    '#fd8d3c',
    '#fdae6b',
    '#31a354'
  ];
  const idx = parseInt(id) % arr.length;
  return arr[idx];
};

您的第 98 行将保持不变 (line(d.id))

https://codepen.io/Alexander9111/pen/mdRZjeW

  1. 您可以使用 CSS 类:https://codepen.io/Alexander9111/pen/oNBrMez
  2. (我的首选方法,保持一切数据驱动)您可以修改数据结构以在此处定义颜色:https://codepen.io/Alexander9111/pen/jOyjpGX

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 2016-06-07
    • 2017-07-03
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多