javascript - 如何在图表 js 中绘制一条线到最高数据点?
问题描述
我一直在使用 Chart JS 文档,但我认为这可能更多是基于问题的计算机科学/数学。我正在尝试绘制一条从图表底部延伸到最高数据点顶部的线。这是一个工作代码示例的链接:https ://stackblitz.com/edit/react-pvzbwc
这个想法是让图表看起来像这样,点正好在数据的顶部结束:https ://i.stack.imgur.com/L8d0H.jpg
到目前为止,这是我的 after draw 钩子:
// draw a line when someone hovers over a data point
afterDatasetDraw: (chart) => {
// console.log(chart)
if (chart.tooltip._active && chart.tooltip._active.length) {
const activePoint = chart.tooltip._active[0];
console.log(activePoint.tooltipPosition())
const ctx = chart.ctx;
const y_axis = chart.scales['y-axis-0'];
const x = activePoint.tooltipPosition().x;
const yData = activePoint._chart.config.data.datasets[activePoint._datasetIndex].data[activePoint._index].y;
const topY = y_axis.top;
const bottomY = y_axis.bottom;
// draw line
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 2;
ctx.strokeStyle = '#000';
ctx.stroke();
ctx.restore();
}
}
当我需要在顶部画一条直线时,它工作得很好,但当我只想在最高数据点的顶部看到它时就不行了。我注意到 topY 是一个静态不变的数字。我想知道是否有一种方法可以根据图表的笛卡尔点计算顶部位置?
任何见解绝对值得赞赏。
解决方案
经过一番挣扎,我已经回答了这个问题。这比我提出的问题要简单得多。事实证明,我只需要计算数据点与图形之间的比率(以像素为单位),然后在该点实现一条线。
我已将其放入带有 API的插件中:
/// default values
lineHeightAnnotation: {
// defaults to have line to the highest data point on every tick
always: true,
// optionally, only have line draw to the highest datapoint nearest the user's hover position
hover: false,
// colors of the line
color: '#000',
// name of yAxis
yAxis: 'y-axis-0',
// weight of the line
lineWeight: 1.5,
/// sets shadow for ALL lines on the canvas
shadow: {
// color of the shadow
color: 'rgba(0,0,0,0.35)',
// blur of the shadow
blur: 10,
/// shadow offset
offset: {
// x offset
x: 0,
// y offset
y: 3
}
},
// dash defaults at [10, 10]
noDash: true,
}
逻辑:
/**
* Vars
* maxY - the tallest data point on the graph
* tickMax - the tallest tick on the y axis
* bottomY - the lowest point of the graph
* additionalOffsets = dataset.borderWidth * 2
*
* bottomY * maxY
* highestDataY = bottomY - ------------------- + additionOffsets
* tickMax
*/
功能:
afterDatasetDraw: (chart) => {
// draw a dashed line when someone hovers over a data point
if (chart.tooltip._active && chart.tooltip._active.length) {
const activePoint = chart.tooltip._active[0];
const ctx = chart.ctx;
const x = activePoint.tooltipPosition().x;
const yAxis = chart.scales['y-axis-0'];
const tickMax = yAxis.ticksAsNumbers[0] // first index is always the tallest
const tickLow = yAxis.ticksAsNumbers[yAxis.ticksAsNumbers.length - 1]
const topY = yAxis.top; // clientRect.top + chart.padding.y
const bottomY = yAxis.bottom; // clientRect.bottom
let maxY = 1;
let borderWidth = 0;
const datasets = chart.config.data.datasets
datasets.forEach((set, i) => {
// get maximum Y value
// get borderWidth of that dataset
let point = set.data[activePoint._index].y
if(point > maxY) {
maxY = parseInt(point, 10) - parseInt(set.borderWidth, 10)
borderWidth = parseInt(set.borderWidth, 10)
}
});
let yBRatio = bottomY * (maxY - tickLow)
let tMRatio = yBRatio / (tickMax - tickLow)
let highestDataY = bottomY - tMRatio + (borderWidth * 2)
// draw line
ctx.save();
ctx.beginPath();
ctx.setLineDash([10, 10]);
ctx.moveTo(x, highestDataY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 1.5;
ctx.strokeStyle = '#000';
ctx.stroke();
ctx.restore();
}
推荐阅读
- django - 如何在 Django 表单中使用 BaseInlineFormSet?
- python - 如何在 wx 框架中将 matplotlib 画布与 wx 面板对齐
- python-3.x - ipython 2.7.15+ -> 3.x
- python - 是否有一个简单的列表表达式可以获取列表中项目的索引但不获取列表中项目的值?
- jquery - 如何从具有相同名称的数组的不同索引索引的多个元素中获取单击的元素
- mongodb - Doctrine ODM - 提供的更新字段
- amazon-web-services - 从 Alexa Skill Lambda 调用 DynamoDB 时出现 CORS 错误
- html - 如何在屏幕调整大小(不滚动)时使导航栏从透明变为实心
- mysql - 如何在 phpmyadmin 上启用事件调度程序
- python - 如何在 Python 中使用 OpenCV 将图像的背景颜色设置为白色