Рисование смешанной горизонтальной полосы / линии с накоплением в chartjs

Я просмотрел документы / примеры для chartjs, но знает ли кто-нибудь способ сделать следующее?

  • Создавать полосы, ширина которых (ось x) может изменяться, но высота всегда полная (а также вся ось y)?
  • Таких столбцов на графике может быть x
  • Создайте линию, которая охватывает всю ось x, но может изменять ее ось y (иначе говоря, не прямую, а извилистую).

У меня здесь грубый рисунок, где желтый - это полосы, а черный - это линия.

Я как бы получил первую часть, используя сложенные стержни и поменяв местами ось, но для оси Y (высота стержней) установлено только 1. Это проблема при попытке нарисовать изогнутую линию в смешанном режиме, так как есть только один y. -Точка оси (вместо множества точек оси Y):

Вот еще одна попытка с несколькими точками оси Y, но я не могу контролировать ширину полосы:

Если кто-нибудь может помочь (или хотя бы сказать мне, иду ли я в правильном направлении), я был бы очень признателен!

Please see code in the jsfiddle link

person ekjcfn3902039    schedule 07.11.2019    source источник
comment
он дублирован stackoverflow.com/questions/25811425/   -  person A Farmanbar    schedule 08.11.2019
comment
Нет, это не дублируется. Это особый случай, который больше нигде не рассматривается.   -  person ekjcfn3902039    schedule 08.11.2019


Ответы (2)


Хм, это сложно ... Единственное решение, которое у меня было бы, - это создать гистограмму с очень большим количеством очень маленьких столбцов.

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

Сейчас возможен только один прямоугольник, но нетрудно улучшить его до нескольких прямоугольников.

Вот весь мой код, такой же, как JSBin:

var chartData = {
  datasets: [{
    type: 'line',
    label: 'Dataset 1',
    borderColor: 'blue',
    borderWidth: 2,
    fill: false,
    data: []
  }, {
    type: 'bar',
    label: 'Dataset 2',
    backgroundColor: 'red',
    data: [],
  }]
};

var newData0 = []
var newData1 = []
var labels = []
var counter = 50

// Rectangle between two random Integers
var rectangleBetween = [Math.round(Math.random()*counter), Math.round(Math.random()*counter)]
rectangleBetween.sort(function(a, b){return a - b})

for (var i = 0; i < counter; i++) {
  labels.push(i)

  // Data for Dataset 1 (line):
  var newObj0 = {}
  newObj0.x = i
  // 50/50 chance of data
  if (Math.random()<0.5) {
    newObj0.y = Math.round(Math.random()*100)
  } else {
    newObj0.y = null
  }
  newData0.push(newObj0)

  // Data for Dataset 2 (bar):
  var newObj1 = {}
  if (i >= rectangleBetween[0] && i <= rectangleBetween[1]) {
    newObj1.x = i
    newObj1.y = 100
  } else {
    newObj1.x = i
    newObj1.y = 0
  }  
  newData1.push(newObj1)
}

chartData.datasets[0].data = newData0
chartData.datasets[1].data = newData1
chartData.labels = labels


var ctx = document.getElementById('chart').getContext('2d');
myMixedChart = new Chart(ctx, {
  type: 'bar',
  data: chartData,
  options: {
    responsive: true,
    spanGaps: true,
    title: {
      display: true,
      text: 'Chart.js Combo Bar Line Chart'
    },
    tooltips: {
      mode: 'index',
      intersect: true
    },
    scales: {
      xAxes: [{
        //barThickness: 80, // number (pixels) or 'flex'
        //maxBarThickness: 100, // number (pixels)
        barPercentage: 1.0,
        categoryPercentage: 1.0,
        gridLines: {
          display: false
        }
      }]
    }
  }
});
person HeadhunterKev    schedule 11.11.2019
comment
FWIW, моя линия на самом деле представляет собой диаграмму рассеяния (с showLines = true) с примерно 2000 точками, и в среднем у меня может быть от 0 до 50 столбцов. - person ekjcfn3902039; 12.11.2019
comment
Я взял ваш пример и сделал небольшой статический образец. Кажется, между планками есть зазоры. Я не знаю, как закрыть эти пробелы. Я также хотел бы поместить рамку вокруг общей формы полосы (вместо границы на каждом отдельном фрагменте полосы). Я также хотел бы иметь некоторую непрозрачность для общей формы полосы (вместо каждого отдельного фрагмента полосы). Вот мои правки: jsbin.com/dubofajefo/1/edit?js,output Возможно ли это на вашем примере? - person ekjcfn3902039; 12.11.2019
comment
Хорошо, я сдаюсь. Я не могу найти способ отображать полосы друг за другом, когда они находятся в одном индексе, он всегда отображает их рядом друг с другом. Вот информация об этом, но только для категории и временной шкалы, а не для линейной шкалы < / а>. Таким образом, возможен только один прямоугольник. Отсюда и зазоры между планками. Я не думаю, что границы возможны для каждых данных, только для полного набор данных. Извините, я не могу вам помочь, я не знаю другого решения. - person HeadhunterKev; 13.11.2019
comment
Я тоже, но спасибо, что изучили это! Я отправляю запрос на добавление функции, если это невозможно. - person ekjcfn3902039; 13.11.2019

Похоже, это лучшее решение:

https://codepen.io/kurkle/pen/ExxdyXQ

var ctx = document.getElementById("chart").getContext("2d");
var chart = new Chart(ctx, {
  type: "horizontalBar",
  data: {
    labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    datasets: [
      {
        label: "Bar1",
        data: [[2.5, 5.7]],
      },
      {
        label: "Bar2",
        data: [[6, 8]],
      },
      {
        label: "Bar3",
        data: [[9,10]],
      },
      {
        label: "Line",
        type: "line",
        backgroundColor: "rgb(75, 192, 192, 0.5)",
        borderColor: "rgb(75, 192, 192)",
        fill: false,
        tension: 0,
        data: [11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
        yAxisID: "line"
      }
    ]
  },
  options: {
    datasets: {
      horizontalBar: {
        backgroundColor: "rgb(255, 99, 132, 0.5)",
        borderColor: "rgb(255, 99, 132)",
        borderWidth: 1,
        barPercentage: 1,
        categoryPercentage: 1,
        yAxisID: "bar"
      }
    },
    scales: {
      yAxes: [
        {
          id: "bar",
          type: 'category',
          stacked: true,
          labels: ['bar'],
          offset: true
        },
        {
          id: "line",
          position: 'right',
          ticks: {
            min: 0,
            stepSize: 1
          }
        }
      ]
    }
  }
});

Кредит оригинальному автору этого кода (Jukka Kurkela aka kurkle). Он ответил на этот вопрос на странице проблем GitHub.

person ekjcfn3902039    schedule 14.11.2019
comment
Намного лучше, чем мое решение. - person HeadhunterKev; 14.11.2019