我遵循
Chart.js
中的标准示例:线性渐变。当我设置选项 beginAtZero: false
时,渐变效果正常。但是,当我设置选项 beginAtZero: true
时,渐变不会考虑最低值。它从图表底部没有数据的地方开始。
如何更改函数以使梯度考虑最低值的位置?
我尝试计算位置:
gradient = ctx.createLinearGradient(0,
Math.max(...chart.getDatasetMeta(0).data.map(item => item.y)), 0,
Math.min(...chart.getDatasetMeta(0).data.map(item => item.y)));
但是,当调用函数
getDradient()
时,数据点位置不可用。
使用您的脚本化
borderColor: function(context, opts)
您提取了 chart
、图表实例以及 chartArea
和
画布 2d 上下文为:
const chart = context.chart;
const {ctx, chartArea} = chart;
您还可以找到以下内容:
const yScaleId = opts._proxy.scales.y.id;
对于具有多个 y 轴的图表,这是严格的方法;实际上,您可能知道 id,在这种情况下,只有默认轴,id 是 y
chart.scales[yScaleId]
及其 min
和 max
值, scaleMin
和 scaleMax
context.dataset.data
并从中得出数据的最小值和最大值,dataMin
和 dataMax
。const fracStart = (dataMin - scaleMin)/(scaleMax - scaleMin),
fracEnd = (dataMax - scaleMin)/(scaleMax - scaleMin);
这些是在线性垂直渐变定义中应替换 0
和 1
的数字,以便第一个颜色对应于最小值,最终颜色对应于最大值。来自您的代码笔的完整代码:
const ctx = document.getElementById('myChart');
let width, height, gradient;
function getGradient(ctx, chartArea, fracStart = 0, fracEnd = 1) {
const chartWidth = chartArea.right - chartArea.left;
const chartHeight = chartArea.bottom - chartArea.top;
if (!gradient || width !== chartWidth || height !== chartHeight) {
// Create the gradient because this is either the first render
// or the size of the chart has changed
width = chartWidth;
height = chartHeight;
gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
const fracMid = (fracStart + fracEnd) / 2;
gradient.addColorStop(fracStart, 'green');
gradient.addColorStop(fracMid, 'yellow');
gradient.addColorStop(fracEnd, 'red');
}
return gradient;
}
new Chart(ctx, {
type: 'line',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [31, 27, 30, 51, 28, 32],
stepped: true,
borderWidth: 4,
borderColor: function(context, opts) {
const chart = context.chart;
const {ctx, chartArea} = chart;
// the id of the y scale of this dataset:
const yScaleId = opts._proxy.scales.y.id;
const scaleMin = chart.scales[yScaleId].min,
scaleMax = chart.scales[yScaleId].max;
const dataMin = Math.min(...context.dataset?.data ?? [scaleMin]),
dataMax = Math.max(...context.dataset?.data ?? [scaleMax]);
const fracStart = (dataMin - scaleMin)/(scaleMax - scaleMin),
fracEnd = (dataMax - scaleMin)/(scaleMax - scaleMin);
if (!chartArea) {
// This case happens on initial chart load
return;
}
return getGradient(ctx, chartArea, fracStart, fracEnd);
},
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
<div>
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
和 codepen 叉子。