Гистограмма, подобная диаграмме с цветными столбцами интенсивности и непрозрачностью для каждого бина, чтобы показать интенсивность - PullRequest
0 голосов
/ 17 апреля 2020

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

Например:

Data = [ {x:2, y:10},{x:2, y:10},{x:2, y:10},{x:8, y:50},{x:8, y:50},{x:8, y:50} ,{x:8, y:50} ];

Бин для {x: 2, y: 10} может иметь количество 3 и, следовательно, иметь непрозрачность 0,2, а бин {x: 8, y : 50} может иметь количество 4, поэтому непрозрачность 1. Остальные ячейки останутся. Мне удалось расположить диаграмму в соответствии с тем, что я ищу, но я не могу найти способ изменить непрозрачность корзины.

Вот моя Скрипка для того, что у меня есть сделано до сих пор

Изображение ниже - то, что я ищу как мой конечный результат. enter image description here

1 Ответ

1 голос
/ 18 апреля 2020

Во-первых, я действительно впечатлен тем, чего вы уже достигли, ваша диаграмма выглядит просто великолепно!

Предполагая, что ваши данные присутствуют в array с именем 'input', я сначала подсчитываю вхождения идентичных объектов с использованием Array.reduce().

const countedData = input.reduce((acc, v) => {
  const existing = acc.find(o => o.x == v.x && o.y == v.y);
  if (existing) {
    existing.count += 1;
  } else {
    acc.push({ x: v.x, y: v.y, count: 1 });
  }
  return acc;
}, []);

С предоставленными вами данными countedData будет содержать следующие объекты.

[
  { "x": 2, "y": 10, "count": 3 },
  { "x": 8, "y": 50, "count": 4 }
]

Тогда я Вам понадобится функция, которая обеспечивает непрозрачность для каждой комбинации x и y:

function getOpacity(x, y) {
  const obj = countedData.find(o => o.x == x && o.y == y);
  if (obj) {
    return obj.count < 4 ? 0.7 : 1;
  }
  return 0.2;
}

Осталось только создать массив backgroundColor, который использует вышеупомянутый getOpacity функция.

backgroundColor: data.map((v, index) => "rgba("+R+", "+G+", "+B+", " + getOpacity(index + 1, i + 25) + ")"),

Пожалуйста, ознакомьтесь с исправленным кодом запуска ниже:

const input = [ {x:2, y:10},{x:2, y:10},{x:2, y:10},{x:8, y:50},{x:8, y:50},{x:8, y:50} ,{x:8, y:50} ];
var labels = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24"];
var data = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1];

const countedData = input.reduce((acc, v) => {
  const existing = acc.find(o => o.x == v.x && o.y == v.y);
  if (existing) {
    existing.count += 1;
  } else {
    acc.push({ x: v.x, y: v.y, count: 1 });
  }
  return acc;
}, []);

function getOpacity(x, y) {
  const obj = countedData.find(o => o.x == x && o.y == y);
  if (obj) {
    return obj.count < 4 ? 0.7 : 1;
  }
  return 0.2;
}

var datasets = [];
var R = 0;
var G = 255;
var B = 2;

for ( var i = 1; i < 26; i ++){
  R += 8;
  G -= 4;
  B += 1;
  datasets.push ({ 
    data: data,
    backgroundColor: data.map((v, index) => "rgba("+R+", "+G+", "+B+", " + getOpacity(index + 1, i) + ")"),
    label: 'Bad Style',
    hoverBackgroundColor: "#7E57C2",
    hoverBorderWidth: 0,
    borderWidth: 1.5,
   });
}

R = 153;
G = 153;
B = 0;
for ( var i = 1; i < 30; i ++) {
  R += 8;
  G -= 5;
  B += 0;
  datasets.push ({ 
    data: data,
    backgroundColor: data.map((v, index) => "rgba("+R+", "+G+", "+B+", " + getOpacity(index + 1, i + 25) + ")"),
    label: 'Bad Style',
    hoverBackgroundColor: "#7E57C2",
    hoverBorderWidth: 0,
    borderWidth: 1.5,
   });
}

var bar_ctx = document.getElementById('bar-chart');
bar_ctx.style.backgroundColor = 'rgba(0,0,0,255)';
var bar_chart = new Chart(bar_ctx, {
    type: 'bar',
    data: {
        labels: labels,
        datasets: datasets
    },
    options: {
     		animation: {
        	duration: 10,
        },
        scales: {
          xAxes: [{ 
          	stacked: true, 
            gridLines: { display: false },
            }],
          yAxes: [{ 
          	stacked: true, 
            gridLines: { display: false },
            }],
        },
        legend: {display: false}
    },
   }
);
<script src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js'></script>
<canvas id="bar-chart" width="600" height="350"></canvas>
...