【发布时间】:2015-10-16 08:31:53
【问题描述】:
【问题讨论】:
-
我的图表运行良好..我只想在我的 LineBar 图表中显示数据值..然后我可以打印我的图表..因为现在我可以通过鼠标事件显示数据值
标签: javascript chart.js
【问题讨论】:
标签: javascript chart.js
后期编辑: Chart.js 有一个官方插件2.7.0+ 可以做到这一点:https://github.com/chartjs/chartjs-plugin-datalabels
原答案:
您可以遍历动画完成上的点/条并显示值
预览
HTML
<canvas id="myChart1" height="300" width="500"></canvas>
<canvas id="myChart2" height="300" width="500"></canvas>
脚本
var chartData = {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [
{
fillColor: "#79D1CF",
strokeColor: "#79D1CF",
data: [60, 80, 81, 56, 55, 40]
}
]
};
var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx).Line(chartData, {
showTooltips: false,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function (dataset) {
dataset.points.forEach(function (points) {
ctx.fillText(points.value, points.x, points.y - 10);
});
})
}
});
var ctx = document.getElementById("myChart2").getContext("2d");
var myBar = new Chart(ctx).Bar(chartData, {
showTooltips: false,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function (dataset) {
dataset.bars.forEach(function (bar) {
ctx.fillText(bar.value, bar.x, bar.y - 5);
});
})
}
});
【讨论】:
onComplete 回调,但是当鼠标悬停在图表的条形上时它也会触发,导致数字由于重绘而闪烁。如果onAnimationComplete 会相同?我无法将此回调与我现有的图表代码一起使用(请参阅底部的var chartBar pastebin.com/tT7yTkGh)
这是 Chart.js 2.3 的更新版本
2016 年 9 月 23 日:编辑了我的代码以使用 v2.3 来处理线/条类型。
重要提示:即使不需要动画,也不要将duration选项改成0,否则会出现chartInstance.controller is undefined错误。
var chartData = {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [
{
fillColor: "#79D1CF",
strokeColor: "#79D1CF",
data: [60, 80, 81, 56, 55, 40]
}
]
};
var opt = {
events: false,
tooltips: {
enabled: false
},
hover: {
animationDuration: 0
},
animation: {
duration: 1,
onComplete: function () {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function (bar, index) {
var data = dataset.data[index];
ctx.fillText(data, bar._model.x, bar._model.y - 5);
});
});
}
}
};
var ctx = document.getElementById("Chart1"),
myLineChart = new Chart(ctx, {
type: 'bar',
data: chartData,
options: opt
});
<canvas id="myChart1" height="300" width="500"></canvas>
【讨论】:
此动画选项适用于条形图上的 2.1.3。
稍微修改了@Ross 的回答
animation: {
duration: 0,
onComplete: function () {
// render the value of the chart above the bar
var ctx = this.chart.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.fillStyle = this.chart.config.options.defaultFontColor;
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
ctx.fillText(dataset.data[i], model.x, model.y - 5);
}
});
}}
【讨论】:
hover: {animationDuration: 0} 以阻止标签在悬停时动画消失
.filter(dataset => !dataset._meta[0].hidden)
如果您使用插件chartjs-plugin-datalabels,那么以下代码选项对象将有所帮助
确保您在 typescript 文件中导入 import 'chartjs-plugin-datalabels'; 或在您的 javascript 文件中添加对 <script src="chartjs-plugin-datalabels.js"></script> 的引用。
options: {
maintainAspectRatio: false,
responsive: true,
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
}
}]
},
plugins: {
datalabels: {
anchor: 'end',
align: 'top',
formatter: Math.round,
font: {
weight: 'bold'
}
}
}
}
【讨论】:
根据 @Ross 对 Chart.js 2.0 及更高版本的回答,我必须进行一些调整以防止条形高度太选择比例边界的情况。
条形图选项的animation属性:
animation: {
duration: 500,
easing: "easeOutQuart",
onComplete: function () {
var ctx = this.chart.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
scale_max = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
ctx.fillStyle = '#444';
var y_pos = model.y - 5;
// Make sure data value does not get overflown and hidden
// when the bar's value is too close to max value of scale
// Note: The y value is reverse, it counts from top down
if ((scale_max - model.y) / scale_max >= 0.93)
y_pos = model.y + 20;
ctx.fillText(dataset.data[i], model.x, y_pos);
}
});
}
}
【讨论】:
ctx.save(),但没有帮助
onComplete 回调是在我将鼠标悬停在栏上时执行的,这会导致重绘和文本似乎闪烁。这是否与 onAnimationComplete 相同?我无法使用onAnimationComplete 用我现有的代码回调(见pastebin.com/tT7yTkGh底部的var chartBar
我认为在 chartJS v2.x 中执行此操作的最佳选择是使用插件,因此选项中没有大量代码。此外,它还可以防止数据在悬停在条形上时消失。
即只需使用这段代码,它注册了一个插件,在绘制图表后添加文本。
Chart.pluginService.register({
afterDraw: function(chartInstance) {
var ctx = chartInstance.chart.ctx;
// render the value of the chart above the bar
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
chartInstance.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
ctx.fillText(dataset.data[i], model.x, model.y - 2);
}
});
}
});
【讨论】:
Chart.defaults.global.tooltips.enabled = false;。该解决方案的问题是 afterDraw 函数被调用了数百次,可能会产生 CPU 开销。尽管如此,这是目前唯一没有眨眼的答案。如果您需要更好地呈现horizontalBar 图表,请使用ctx.textAlign = 'left'; ctx.textBaseline = 'middle'; 和ctx.fillText(dataset.data[i], model.x+5, model.y);。
按照这个good answer,我会使用这些选项来制作条形图:
var chartOptions = {
animation: false,
responsive : true,
tooltipTemplate: "<%= value %>",
tooltipFillColor: "rgba(0,0,0,0)",
tooltipFontColor: "#444",
tooltipEvents: [],
tooltipCaretSize: 0,
onAnimationComplete: function()
{
this.showTooltip(this.datasets[0].bars, true);
}
};
window.myBar = new Chart(ctx1).Bar(chartData, chartOptions);
这仍然使用了工具提示系统和他的优点(自动定位、模板,...),但隐藏了装饰(背景颜色,插入符号,...)
【讨论】:
this.datasets[0].points 而不是 .bars。我确实更喜欢这个解决方案,因为它使用了工具提示系统。
onComplete 回调中使用了 potatopeelings 和 Huang Trang 的答案,但即使将鼠标悬停在图表的条形上也会触发它,这会导致文本重绘并产生不需要的闪烁效果。我也试过 afterDraw 和它都是一样的。奇怪的是它不会发生在potatopeelings提供的小提琴中。请问有什么想法吗?
来自 chart.js 示例(文件 Chart.js-2.4.0/samples/data_labelling.html):
``` // 定义一个插件来提供数据标签
Chart.plugins.register({
afterDatasetsDraw: function(chartInstance, easing) {
// To only draw at the end of animation, check for easing === 1
var ctx = chartInstance.chart.ctx;
chartInstance.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.getDatasetMeta(i);
if (!meta.hidden) {
meta.data.forEach(function(element, index) {
// Draw the text in black, with the specified font
ctx.fillStyle = 'rgb(0, 0, 0)';
var fontSize = 16;
var fontStyle = 'normal';
var fontFamily = 'Helvetica Neue';
ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
// Just naively convert to string for now
var dataString = dataset.data[index].toString();
// Make sure alignment settings are correct
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var padding = 5;
var position = element.tooltipPosition();
ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);
});
}
});
}
});
```
【讨论】:
我推荐使用这个插件:https://github.com/chartjs/chartjs-plugin-datalabels
只需将插件导入 js 文件,即可将标签添加到图表中,例如:
import 'chartjs-plugin-datalabels'
并且可以使用这些文档进行微调:https://chartjs-plugin-datalabels.netlify.com/options.html
【讨论】:
根据我的经验,一旦包含chartjs-plugin-datalabels 插件(确保将<script> 标记放在页面上的chart.js 标记之后),您的图表就会开始显示值。
如果您随后选择,您可以自定义它以满足您的需求。 The customization is clearly documented here 但基本上,格式就像这个假设的例子:
var myBarChart = new Chart(ctx, {
type: 'bar',
data: yourDataObject,
options: {
// other options
plugins: {
datalabels: {
anchor :'end',
align :'top',
// and if you need to format how the value is displayed...
formatter: function(value, context) {
return GetValueFormatted(value);
}
}
}
}
});
【讨论】:
稍微编辑了@ajhuddy 的回答。 仅适用于条形图。我的版本添加:
缺点:将鼠标悬停在其中包含值的条上时,该值可能看起来有点锯齿状。我还没有找到禁用悬停效果的解决方案。它可能还需要根据您自己的设置进行调整。
配置:
bar: {
tooltips: {
enabled: false
},
hover: {
animationDuration: 0
},
animation: {
onComplete: function() {
this.chart.controller.draw();
drawValue(this, 1);
},
onProgress: function(state) {
var animation = state.animationObject;
drawValue(this, animation.currentStep / animation.numSteps);
}
}
}
助手:
// Font color for values inside the bar
var insideFontColor = '255,255,255';
// Font color for values above the bar
var outsideFontColor = '0,0,0';
// How close to the top edge bar can be before the value is put inside it
var topThreshold = 20;
var modifyCtx = function(ctx) {
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
return ctx;
};
var fadeIn = function(ctx, obj, x, y, black, step) {
var ctx = modifyCtx(ctx);
var alpha = 0;
ctx.fillStyle = black ? 'rgba(' + outsideFontColor + ',' + step + ')' : 'rgba(' + insideFontColor + ',' + step + ')';
ctx.fillText(obj, x, y);
};
var drawValue = function(context, step) {
var ctx = context.chart.ctx;
context.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
var textY = (model.y > topThreshold) ? model.y - 3 : model.y + 20;
fadeIn(ctx, dataset.data[i], model.x, textY, model.y > topThreshold, step);
}
});
};
【讨论】:
calculateTickRotation,它在 Scale 函数中。我来分析一下。
为了防止您的数字在太靠近画布顶部时被截断:
yAxes: [{
ticks: {
stepSize: Math.round((1.05*(Math.max.apply(Math, myListOfyValues)) / 10)/5)*5,
suggestedMax: 1.05*(Math.max.apply(Math, myListOfyValues)),
beginAtZero: true,
precision: 0
}
}]
10 = 滴答数
5 = 将刻度值四舍五入到最接近的 5 - 所有 y 值将均匀递增
1.05 = 增加最大 y 轴刻度值,这样数字就不会被截断
类似的方法也适用于 xAxes。
【讨论】: