Установите минимальное количество шагов на линейном графике

#javascript #chart.js

Вопрос:

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

Вот что у меня под options :

 scales: {
    yAxes: [{
        ticks: {
            beginAtZero: true,
            callback: function (value) { if (Number.isInteger(value)) {return value; } }
        }
    }]
}
 

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

введите описание изображения здесь

Я пробовал использовать эту max: 10 опцию, но затем данные сокращаются, если у меня более 10 заказов. Я не мог найти такого варианта minSteps: 10 или что-то в этом роде. Кто-нибудь знает решение этой проблемы?

Ответ №1:

Вы можете просто использовать второй набор данных со всеми значениями 10, а затем сделать его прозрачным, недоступным для просмотра, чтобы не отображалась подсказка, и скрыть его в легенде:

 var options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [0, 0, 0, 0, 0, 0],
        borderColor: 'blue'
      },
      {
        label: 'filler',
        data: [10, 10, 10, 10, 10, 10],
        borderWidth: 1,
        fill: false,
        pointHitRadius: 0,
        radius: 0,
        hoverRadius: 0,
        borderColor: '#00000000'
      }
    ]
  },
  options: {
    legend: {
      labels: {
        filter: (lEl) => (lEl.text !== 'filler')
      }
    },
    scales: {
      yAxes: [{
        ticks: {
          reverse: false
        }
      }]
    }
  }
}

var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options); 
 <body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</body> 

Редактировать:

Вы можете использовать эту suggestedMax опцию, это приведет к тому, что он всегда будет показывать 10 как максимум, если данные не будут превышать его, тогда он автоматически настроит максимальное значение на все, что нужно для данных.

 var options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      label: '# of Votes',
      data: [0, 0, 0, 0, 0, 0],
      borderColor: 'blue'
    }]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          suggestedMax: 10
        }
      }]
    }
  }
}

var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options); 
 <body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</body> 

Комментарии:

1. Я надеялся на менее «банальный» способ добиться этого. Тем не менее это работает, и я беру то, что могу получить, спасибо!

2. Просто подумал о лучшем способе, обновил ответ

3. Я пробовал suggestedMax раньше (не получилось). Наверное, я неправильно его использовал. Теперь это работает, спасибо за обновление!

Ответ №2:

Добавление к ответу/комментариям, представленным @LeeLenalee, я обновил код до chart.js v. 3x

Следовательно, я бы рекомендовал:

  1. обновление до последней версии версии chart.js v3.5.1:
    в коде у вас есть обе ссылки
    улучшенная производительность и новые опции, особенно если данные содержат даты, как в вашем случае. (v3.x не имеет обратной совместимости с v2.x)
  2. используйте Декартову Ось Времени
    обратите внимание на разницу между «временем» (равноудаленность) и «временными рядами» (в зависимости от того, есть ли точка данных)
    , и вам придется добавить momentjs и chartjs-adapter-moment (см. Фрагмент кода) или добавить luxon и т. Д… как предложил @LeeLenalee (ежедневный просмотр по оси x, еженедельно, ежемесячно, ежегодно — moment.js обрабатывает фильтрацию). Пригодится вам 😜

Пожалуйста, сообщите, правильна ли следующая среда и структура данных (я угадал вашу структуру данных):

 let yourDataJson = [{x: '2021-08-13', y: 20.2},{x: '2021-08-15', y: 16},{x: '2021-08-19', y: 9},{x: '2021-08-23', y: 35},{x: '2021-09-02', y: 2}];

let yourData = {
  datasets: [{
    label: 'Orders: Product A',
    data: yourDataJson,
    borderColor: 'rgba(0,0,255,1)',
    backgroundColor: 'rgba(0,0,255,0.5)',
    fill: true
  }
  ]
};

let yourOptions = {
  scales: {
    x: { // <-- v3.x now object "{", not array "[{" anymore
      type: 'timeseries', // <-- try "time" and "timeseries" to see difference
      time: {
        unit: 'day', // <-- set 'hour' / 'day' / 'week' / 'month' or 'year'
        displayFormats: {
          hour: 'h:mm a',
          day: 'ddd, MMM DD, YYYY',
          week: 'dddd',
          month: 'MMM'
        },
        tooltipFormat: 'dddd, MMM DD, YYYY' // <-- new in v3.x
      },
      ticks: {
        minRotation: 80, // avoiding overlapping of x-Axis ticks
        maxRotation: 90
      }
    },
    y: { // <-- v3.x now object "{", not array "[{" anymore
      ticks: {
        beginAtZero: true,
        callback: function (value) {
          if (Number.isInteger(value)) return value;
        }
      },
      suggestedMin: 0,
      // the data maximum used for determining the ticks is Math.max(dataMax, suggestedMax)
      suggestedMax: 10
    }
  }
};

const ctx = document.getElementById('chartJSContainer').getContext('2d');
const myChart = new Chart(ctx, {
  type: 'line',
  data: yourData,
  options: yourOptions
});

document.querySelector('#btnTime').addEventListener('click', () => {
  myChart.options.scales['x'].type = 'time';
  myChart.update();
});
document.querySelector('#btnTimeseries').addEventListener('click', () => {
  myChart.options.scales['x'].type = 'timeseries';
  myChart.update();
}); 
 <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script> -->

<!-- get the latest version of Chart.js, now at v3.5.1 -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<!-- for x-Axis type 'time' or 'timeseries' to work, you need additional libraries -->
<!-- (like moment.js and its adapter) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script>

<button id='btnTime'>time</button>
<button id='btnTimeseries'>timeseries</button>

<canvas id="chartJSContainer" width="600" height="400"></canvas> 

Комментарии:

1. Лучше использовать luxon или date-fns, значительно снижающие производительность, влияющие на библиотеки, также это приведет к той же проблеме, что он не отображает полные целые числа, и если вы показываете только полные целые числа, он показывает только 0 и 1, и это то, чего он явно не хотел

2. Также stepSize: 10 не заставит минимум 10 единиц к показу, она делает так, что между каждой ТИК есть 10, так что, если ваш диапазон оси от 1 до 100 имеется 10 клещей, а если ваш диапазон оси от 1 до 20 у вас есть только 2 галочки, которая по-прежнему дает ту же проблему, имеющих большой разрыв jsfiddle.net/Leelenaleee/w0cxq8r9/1