我需要能够设置固定的列宽。例如,如果我指定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>
如果我正确理解了您的问题,那么下面的代码片段将达到您想要的结果。
根据两个输入参数(宽度和点数),它调整图表的右填充以将点保持在指定的宽度上,而不管要填充画布宽度的点太多还是太少。 >
出于演示目的,您可以更改输入值,然后按“更新”按钮以查看结果。
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>