D3: объединить две цветовые гаммы в одну - PullRequest
0 голосов
/ 15 октября 2018

В настоящее время у меня есть две переменные, которые я могу сопоставить двум разным цветам на двух цветовых шкалах s1 и s2.s1 дает мне оттенок красного, соответствующий значению моей переменной X (4 различных возможных цвета).s1 дает мне оттенок синего, соответствующий значению моей переменной Y (также 4 различных возможных цвета).

Теперь то, что я хотел бы получить, это то, что позволяет мне комбинировать эти два, чтобы получить уникальный цвет для комбинации переменных.Поэтому для пары (X, Y) я получаю цвет по шкале.Таким образом, я получаю шкалу из 16 возможных цветов.

Вот легенда, иллюстрирующая то, что я ищу:

enter image description here

Я просматривал примеры в Интернете, но не могу понять, как этого добиться.

1 Ответ

0 голосов
/ 15 октября 2018

Вы можете довольно легко объединить две пороговые шкалы в новую функцию шкалы.Ядро функции может выглядеть следующим образом:

d3.scaleBivariate = function() {
  function scaleBivariate(value) {
    var r = reds(value[0]);
    var b = blues(value[1]);

    return "rgb("+r+","+((r+b)/2)+","+b+")";
  }

  var blues = d3.scaleThreshold()
    .range([255,205,155,105,55])
    .domain([0,1,2,3,4,5]);

  var reds = d3.scaleThreshold()
    .range([255,205,155,105,55])
    .domain([0,1,2,3,4,5]);

  return scaleBivariate;

}

Это устанавливает красный и синий каналы с помощью двух пороговых шкал d3.Зеленый просто устанавливается как среднее между двумя, хотя вы можете установить его на то, что желательно, скажем, 0 или минимум двух других каналов.Мои красные / синие диапазоны произвольны и легко меняются.

Выше можно использовать как:

d3.scaleBivariate = function() {
  function scaleBivariate(value) {
    var r = reds(value[0]);
    var b = blues(value[1]);

    return "rgb("+r+","+((r+b)/2)+","+b+")";
  }

  var blues = d3.scaleThreshold()
    .range([255,205,155,105,55])
    .domain([0,1,2,3,4,5]);
        
  var reds = d3.scaleThreshold()
    .range([255,205,155,105,55])
    .domain([0,1,2,3,4,5]);
        
  return scaleBivariate;

}

// Dummy data:
var data = d3.range(16).map(function(d) {
  return {x: d%4, y: Math.floor(d/4) }
})


var svg = d3.select("svg");
var size = 30;

var color = d3.scaleBivariate();

svg.selectAll("rect")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", function(d) { return d.x * size })
  .attr("y", function(d) { return d.y * size })
  .attr("width",size)
  .attr("height",size)
  .attr("fill",function(d) {
    return color([d.x,d.y]);
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.0.0/d3.min.js"></script>

<svg></svg>

Конечно, вы можете добавить некоторую гибкость, добавляя методы для изменения того, какое базовое свойство устанавливает, какие цвета связаны с какими свойствами, какими должны быть пороги,и т. д. Чтобы привести базовый пример, в приведенном ниже примере добавлены средства доступа для установки того, какое свойство должно отображаться на синие и красные каналы:

d3.scaleBivariate = function() {

  function scaleBivariate(value) {
     var r = reds(red(value));
     var b = blues(blue(value));
     return "rgb("+r+","+((r+b)/2)+","+b+")";
  }
  
  var blues = d3.scaleThreshold()
    .range([255,205,155,105,55])
    .domain([0,1,2,3,4,5]);
    
  var reds = d3.scaleThreshold()
    .range([255,205,155,105,55])
    .domain([0,1,2,3,4,5]);
    
  var red = function(d) { return d[0]; }
  
  var blue = function(d) { return d[1];}
  
  // Accessors:
  scaleBivariate.red = function(_) {
    return arguments.length ? (red = _, scaleBivariate): red;
  }
  
  scaleBivariate.blue = function(_) {
    return arguments.length ? (blue = _, scaleBivariate): blue;  
  }
  
  return scaleBivariate;
}

var data = d3.range(16).map(function(d) {
  return {x: d%4, y: Math.floor(d/4) }
})

var svg = d3.select("svg");
var size = 30;

// set up the color scale:
var color = d3.scaleBivariate()
  .red(function(d) { return d.x; })
  .blue(function(d) { return d.y; });

svg.selectAll("rect")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", function(d) { return d.x * size })
  .attr("y", function(d) { return d.y * size })
  .attr("width",size)
  .attr("height",size)
  .attr("fill",color);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.0.0/d3.min.js"></script>

<svg></svg>
...