Javascript Chart.js — 绘制任意垂直线
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30256695/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chart.js — drawing an arbitrary vertical line
提问by Fredrik
How can I draw an vertical line at a particular point on the x-axis using Chart.js?
如何使用 Chart.js 在 x 轴上的特定点绘制一条垂直线?
In particular, I want to draw a line to indicate the current day on a LineChart. Here's a mockup of the chart: http://i.stack.imgur.com/VQDWR.png
特别是,我想画一条线来指示 LineChart 上的当前日期。这是图表的模型:http: //i.stack.imgur.com/VQDWR.png
回答by potatopeelings
Update- this answer is for Chart.js 1.x, if you are looking for a 2.x answer check the comments and other answers.
更新- 此答案适用于 Chart.js 1.x,如果您正在寻找 2.x 答案,请查看评论和其他答案。
You extend the line chart and include logic for drawing the line in the draw function.
您扩展折线图并在 draw 函数中包含用于绘制线条的逻辑。
Preview
预览
HTML
HTML
<div>
<canvas id="LineWithLine" width="600" height="400"></canvas>
</div>
Script
脚本
var data = {
labels: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
datasets: [{
data: [12, 3, 2, 1, 8, 8, 2, 2, 3, 5, 7, 1]
}]
};
var ctx = document.getElementById("LineWithLine").getContext("2d");
Chart.types.Line.extend({
name: "LineWithLine",
draw: function () {
Chart.types.Line.prototype.draw.apply(this, arguments);
var point = this.datasets[0].points[this.options.lineAtIndex]
var scale = this.scale
// draw line
this.chart.ctx.beginPath();
this.chart.ctx.moveTo(point.x, scale.startPoint + 24);
this.chart.ctx.strokeStyle = '#ff0000';
this.chart.ctx.lineTo(point.x, scale.endPoint);
this.chart.ctx.stroke();
// write TODAY
this.chart.ctx.textAlign = 'center';
this.chart.ctx.fillText("TODAY", point.x, scale.startPoint + 12);
}
});
new Chart(ctx).LineWithLine(data, {
datasetFill : false,
lineAtIndex: 2
});
The option property lineAtIndex controls which point to draw the line at.
选项属性 lineAtIndex 控制在哪个点绘制线。
Fiddle - http://jsfiddle.net/dbyze2ga/14/
回答by Tomá? Dvo?ák
Sharing my solution for chartjs.org version 2.5. I wanted to use a plugin, to make the implementation reusable.
分享我的 chartjs.org 2.5 版解决方案。我想使用一个插件,使实现可重用。
const verticalLinePlugin = {
getLinePosition: function (chart, pointIndex) {
const meta = chart.getDatasetMeta(0); // first dataset is used to discover X coordinate of a point
const data = meta.data;
return data[pointIndex]._model.x;
},
renderVerticalLine: function (chartInstance, pointIndex) {
const lineLeftOffset = this.getLinePosition(chartInstance, pointIndex);
const scale = chartInstance.scales['y-axis-0'];
const context = chartInstance.chart.ctx;
// render vertical line
context.beginPath();
context.strokeStyle = '#ff0000';
context.moveTo(lineLeftOffset, scale.top);
context.lineTo(lineLeftOffset, scale.bottom);
context.stroke();
// write label
context.fillStyle = "#ff0000";
context.textAlign = 'center';
context.fillText('MY TEXT', lineLeftOffset, (scale.bottom - scale.top) / 2 + scale.top);
},
afterDatasetsDraw: function (chart, easing) {
if (chart.config.lineAtIndex) {
chart.config.lineAtIndex.forEach(pointIndex => this.renderVerticalLine(chart, pointIndex));
}
}
};
Chart.plugins.register(verticalLinePlugin);
Usage is simple then:
用法很简单:
new Chart(ctx, {
type: 'line',
data: data,
label: 'Progress',
options: options,
lineAtIndex: [2,4,8],
})
The code above inserts red vertical lines at positions 2,4 and 8, running through points of first dataset at those positions.
上面的代码在位置 2,4 和 8 处插入红色垂直线,穿过这些位置的第一个数据集的点。
回答by Brandon Johnson
I had to go through the trouble of figuring out how to do something similar with ChartJS 2.0 so I thought I would share.
我不得不经历弄清楚如何用 ChartJS 2.0 做类似事情的麻烦,所以我想我会分享。
This is based on the new way of overriding a chart prototype as explained here: https://github.com/chartjs/Chart.js/issues/2321
这是基于覆盖图表原型的新方法,如下所述:https: //github.com/chartjs/Chart.js/issues/2321
var ctx = document.getElementById('income-chart');
var originalDraw = Chart.controllers.line.prototype.draw;
Chart.controllers.line.prototype.draw = function (ease) {
originalDraw.call(this, ease);
var point = dataValues[vm.incomeCentile];
var scale = this.chart.scales['x-axis-0'];
// calculate the portion of the axis and multiply by total axis width
var left = (point.x / scale.end * (scale.right - scale.left));
// draw line
this.chart.chart.ctx.beginPath();
this.chart.chart.ctx.strokeStyle = '#ff0000';
this.chart.chart.ctx.moveTo(scale.left + left, 0);
this.chart.chart.ctx.lineTo(scale.left + left, 1000000);
this.chart.chart.ctx.stroke();
// write label
this.chart.chart.ctx.textAlign = 'center';
this.chart.chart.ctx.fillText('YOU', scale.left + left, 200);
};
回答by phifi
I'd highly recommend to use the Chartjs-Plugin-Annotation.
我强烈建议使用Chartjs-Plugin-Annotation。
An example can be found at CodePen
可以在CodePen上找到一个示例
var chartData = {
labels: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
datasets: [
{
data: [12, 3, 2, 1, 8, 8, 2, 2, 3, 5, 7, 1]
}
]
};
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
new Chart(ctx, {
type: "line",
data: chartData,
options: {
annotation: {
annotations: [
{
type: "line",
mode: "vertical",
scaleID: "x-axis-0",
value: "MAR",
borderColor: "red",
label: {
content: "TODAY",
enabled: true,
position: "top"
}
}
]
}
}
});
};
Have a look here for more Details: https://stackoverflow.com/a/36431041
在这里查看更多详细信息:https: //stackoverflow.com/a/36431041
回答by Gray Kemmey
Here's a pen that achieves a similar effect without the chartjs-plugin-annotation, or hacking how Chart.js renders, or any other plugins: https://codepen.io/gkemmey/pen/qBWZbYM
这是一个无需chartjs-plugin-annotation,或hacking Chart.js渲染方式或任何其他插件即可实现类似效果的笔:https://codepen.io/gkemmey/pen/qBWZbYM
Approach
方法
- Use a combo bar / line chart, and use the bar chart to draw the vertical lines.
- Use two y-axes: one for the bar chart (which we don't display), and one for all your other line chart datasets.
- Force the bar chart y-axes to
min: 0andmax: 1. Anytime you want to draw a vertical line, add a data object like{ x: where_the_line_goes, y: 1 }to your bar chart dataset. - The pen also adds some custom data to the bar chart dataset and a legend filter and label callback to exclude the bar chart dataset from the legend, and control the label on the vertical line.
- 使用组合条形图/折线图,并使用条形图绘制垂直线。
- 使用两个 y 轴:一个用于条形图(我们不显示),另一个用于所有其他折线图数据集。
- 将条形图 y 轴强制为
min: 0和max: 1。任何时候您想绘制一条垂直线,都可以{ x: where_the_line_goes, y: 1 }向条形图数据集添加一个数据对象。 - 笔还在条形图数据集中添加了一些自定义数据和图例过滤器和标签回调,以从图例中排除条形图数据集,并控制垂直线上的标签。
Pros
优点
- No other dependencies. No custom monkey patching / extending.
- The annotations plugin doesn't seem to be actively maintained. For instance, atm, their event handlers throw an error about "preventing default on passive events"
- Maybe a pro: The annotations plugin always shows the labels of lines drawn, and you have to use their event callbacks to get a show-on-hover effect. Chart.js tooltips show on hover by default.
- 没有其他依赖。没有自定义猴子修补/扩展。
- 注释插件似乎没有得到积极维护。例如,atm,他们的事件处理程序会抛出关于“防止被动事件默认”的错误
- 也许专业人士:注释插件总是显示绘制的线条的标签,你必须使用它们的事件回调来获得悬停显示效果。Chart.js 工具提示默认显示在悬停时。
Cons
缺点
- We're adding custom data in the dataset config, and hoping it doesn't conflict with anything Chart.js is doing. It's data Chart.js doesn't expect to be there, but as of 2.8, also doesn't break it.
- 我们在数据集配置中添加自定义数据,并希望它不会与 Chart.js 正在做的任何事情发生冲突。这是 Chart.js 不希望存在的数据,但从 2.8 开始,也不会破坏它。


