如何在chart.js中使固定宽度的列不具有ticks.min / max?

问题描述 投票:1回答:1

我需要能够设置固定的列宽。例如,如果我指定50像素且画布宽度为500像素,则Chart.JS呈现10列,并自动将ticks.min / max设置为0和9。

我知道条形图中的barThickness和barPercentage。但是我有线路图。我知道maxTicksLimit,但仅适用于“线性”比例类型(我有“类别”比例类型)。我找到了解决方案。我使用onResize回调并做一些技巧(选择画布宽度,然后将其除以所需的列宽度,然后设置ticks.min / max)。这是可行的,但效果不好,因为结果未达到预期的宽度。还有更多问题,如果您有500px的画布和5个数据项并且您需要50px的列宽。在这种情况下,Chart.JS将按画布宽度拉伸列。

没有我的把戏的清楚示例。

const ITEMS_COUNT = 50;
const MIN = -5000;
const MAX = 8000;

const defaultDatasetOptions = {
  pointRadius: 0,
  pointHoverRadius: 0,
  pointBorderWidth: 0,
  pointHoverBorderWidth: 0,
  pointHitRadius: 10,
  borderWidth: 0
};

const data = {
  labels: _.range(1, ITEMS_COUNT),
  datasets: [
    {
      ...defaultDatasetOptions,
      label: 'Series 1',
      data: Array.from(Array(ITEMS_COUNT), () => _.random(MIN, MAX)),
      backgroundColor: 'rgba(255, 0, 0, .3)'
    },
    {
      ...defaultDatasetOptions,
      label: 'Series 2',
      data: Array.from(Array(ITEMS_COUNT), () => _.random(MIN, MAX)),
      backgroundColor: 'rgba(0, 255, 0, .3)'
    },
    {
      ...defaultDatasetOptions,
      label: 'Series 3',
      data: Array.from(Array(ITEMS_COUNT), () => _.random(MIN, MAX)),
      backgroundColor: 'rgba(0, 0, 255, .3)'
    }
  ]
};

const options = {
  legend: {
    display: false
  },
  scales: {
    xAxes: [
      {
        type: 'category',
        gridLines: {
          offsetGridLines: true,
          color: 'orange',
          tickMarkLength: 0,
          drawBorder: false
        },
        ticks: {
          display: false,
          maxRotation: 0,
          beginAtZero: true,
          autoSkip: false,
          stepSize: 1
        },
        offset: true
      }
    ],
    yAxes: [{ display: false }]
  },
  tooltips: {
    mode: 'index',
    intersect: false
  },
  hover: {
    mode: 'index',
    intersect: false
  }
};

new Chart(document.querySelector('canvas'), {
  type: 'line',
  data,
  options
});
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>

<canvas></canvas>

我的解决方案示例。

const ITEMS_COUNT = 50;
const MIN = -5000;
const MAX = 8000;

const COLUMN_WIDTH = 50;

const defaultDatasetOptions = {
  pointRadius: 0,
  pointHoverRadius: 0,
  pointBorderWidth: 0,
  pointHoverBorderWidth: 0,
  pointHitRadius: 10,
  borderWidth: 0
};

const data = {
  labels: _.range(1, ITEMS_COUNT + 1),
  datasets: [
    {
      ...defaultDatasetOptions,
      label: 'Series 1',
      data: Array.from(Array(ITEMS_COUNT), () => _.random(MIN, MAX)),
      backgroundColor: 'rgba(255, 0, 0, .3)'
    },
    {
      ...defaultDatasetOptions,
      label: 'Series 2',
      data: Array.from(Array(ITEMS_COUNT), () => _.random(MIN, MAX)),
      backgroundColor: 'rgba(0, 255, 0, .3)'
    },
    {
      ...defaultDatasetOptions,
      label: 'Series 3',
      data: Array.from(Array(ITEMS_COUNT), () => _.random(MIN, MAX)),
      backgroundColor: 'rgba(0, 0, 255, .3)'
    }
  ]
};

const options = {
  onResize: setupTicksMinMax,
  legend: {
    display: false
  },
  scales: {
    xAxes: [
      {
        type: 'category',
        gridLines: {
          offsetGridLines: true,
          color: 'orange',
          tickMarkLength: 0,
          drawBorder: false
        },
        ticks: {
          display: false,
          maxRotation: 0,
          beginAtZero: true,
          autoSkip: false,
          stepSize: 1
        },
        offset: true
      }
    ],
    yAxes: [{ display: false }]
  },
  tooltips: {
    mode: 'index',
    intersect: false
  },
  hover: {
    mode: 'index',
    intersect: false
  }
};

const setupTicksMinMax = (chartInstance) => {
  const xScale = chartInstance.scales['x-axis-0'];

  xScale.options.ticks.min = chartInstance.data.labels[0];
  xScale.options.ticks.max = chartInstance.data.labels[Math.ceil(chartInstance.canvas.width / COLUMN_WIDTH)];

  chartInstance.update(0);
};

const chartInstance = new Chart(document.querySelector('canvas'), {
  type: 'line',
  data,
  options
});

setupTicksMinMax(chartInstance);
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>

<canvas></canvas>
javascript chart.js
1个回答
0
投票

如果我正确理解了您的问题,那么下面的代码片段将达到您想要的结果。

根据两个输入参数(宽度和点数),它调整图表的右填充以将点保持在指定的宽度上,而不管要填充画布宽度的点太多还是太少。 >

出于演示目的,您可以更改输入值,然后按“更新”按钮以查看结果。

let chart = new Chart(document.getElementById("chart"), {
  type: "line",
  data: {
    datasets: [{
      data: []
    }]
  },
  options: {
    maintainAspectRatio: false,
    legend: {
      display: false
    },
    scales: {
      xAxes: [{
        type: 'category',
        gridLines: {
          offsetGridLines: true,
          color: 'orange',
          tickMarkLength: 0,
          drawBorder: false
        },
        ticks: {
          display: false,
          maxRotation: 0,
          beginAtZero: true,
          autoSkip: false,
          stepSize: 1
        },
        offset: true
      }],
      yAxes: [{
        display: false
      }]
    }
  },
  plugins: [{
    resize: function(chart) {
      update(chart);
    }
  }]
});

function update(chart) {
  let pointWidth = parseInt(document.getElementById("pw").value),
    pointCount = parseInt(document.getElementById("pc").value),
    width = chart.width - chart.chartArea.left,
    points = Math.floor(width / pointWidth);

  if (points > pointCount) {
    points = pointCount;
  }

  chart.config.data.labels = _.range(1, points + 1);
  chart.config.data.datasets[0].data = Array.from(Array(pointCount), () => _.random(-5000, 8000));
  chart.options.layout.padding.right = width - (pointWidth * points);

  chart.update();
}

document.getElementById("update").addEventListener("click", function() {
  update(chart);
});
canvas {
  background-color: #f5f5f5
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<p>
  Width: <input id="pw" type="text" value="50">px Count: <input id="pc" type="text" value="5"><button id="update">Update</button>
</p>
<canvas id="chart"></canvas>
© www.soinside.com 2019 - 2024. All rights reserved.