Как изменить цвет линии на основе данных - график или график. js - PullRequest
0 голосов
/ 14 февраля 2020

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

Пример набора данных:

[
    {time: '3:00:00', speed: 20, direction: 345},
    {time: '3:01:00', speed: 0, direction: 0},
    {time: '3:02:00', speed: 25, direction: 90},
    {time: '3:03:00', speed: 10, direction: 180},
    {time: '3:04:00', speed: 5, direction: 0}
]

Я ищу время для оси x, скорость для оси y, а затем для изменения цвета отрезка в зависимости от направления. Похоже, что большинство библиотек диаграмм (если я не начну копаться в d3), когда они создают линейные графики, создают одну большую линию для всей серии и не позволяют стилизовать отдельные сегменты линии. Здесь есть отличный пример диаграммы js, но цвет не основан на данных (это просто произвольный набор цветов):

https://blog.vanila.io/chart-js-tutorial-how-to-make-gradient-line-chart-af145e5c92f9

Ответы [ 2 ]

2 голосов
/ 15 февраля 2020

Вы можете создать диаграмму scatter и нарисовать линии прямо на холсте, используя Plugin Core API . API предлагает ряд хуков, которые могут использоваться для выполнения пользовательского кода.

В следующем фрагменте кода я использую хук afterDraw для рисования линий связи между точками данных. Их цвет зависит от свойства direction начальной точки данных.

const rawData = [
    {time: '3:00:00', speed: 20, direction: 345},
    {time: '3:01:00', speed: 0, direction: 0},
    {time: '3:02:00', speed: 25, direction: 290},
    {time: '3:03:00', speed: 10, direction: 180},
    {time: '3:04:00', speed: 5, direction: 0}
];
const data = rawData.map(o => ({ x: moment(o.time, 'H:mm:ss').toDate().getTime(), y: o.speed}));
const colorsPer100 = ['green', 'orange', 'blue', 'red']; 

new Chart(document.getElementById("myChart"), {
  type: "scatter",
  plugins: [{
    afterDraw: chart => {      
      var ctx = chart.chart.ctx; 
      var xAxis = chart.scales['x-axis-1'];
      var yAxis = chart.scales['y-axis-1'];      
      chart.config.data.datasets[0].data.forEach((value, index) => {
        if (index > 0) {        
           var valueFrom = data[index - 1];
           var xFrom = xAxis.getPixelForValue(valueFrom.x);     
           var yFrom = yAxis.getPixelForValue(valueFrom.y);     
           var direction = rawData[index -1].direction;
           var xTo = xAxis.getPixelForValue(value.x);         
           var yTo = yAxis.getPixelForValue(value.y); 
           ctx.save();           
           ctx.strokeStyle = colorsPer100[Math.floor(direction / 100)];           
           ctx.lineWidth = 2;
           ctx.beginPath();
           ctx.moveTo(xFrom, yFrom);             
           ctx.lineTo(xTo, yTo);
           ctx.stroke();
           ctx.restore();
        }
      });      
    }
  }],
  data: {
    datasets: [{
      label: "My Dataset",
      data: data,
      borderColor: "rgb(75, 192, 192)"
    }]
  },
  options: {
    legend: {
      display: false
    },
    scales: {
      xAxes: [{
        type: 'time',
        time: {
          unit: 'minute',
          displayFormats: {
            minute: 'H:mm:ss'
          }
        },
      }]
    }
  }  
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="90"></canvas>
0 голосов
/ 16 февраля 2020

Уминдер имеет интересное решение. В другой ветке кто-то опубликовал решение, с которым я согласился - они просто создали массив цветов того же размера, что и набор данных (и просто передали его вместе с данными). Это отлично сработало и оказалось намного проще, чем я думаю, я пытался это сделать.

...