Chart.js - Add text/label to bubble chart elements without using tooltips? - javascript

Question
Is there any way to add labels to the individual bubbles in a Chart.js bubble chart without resorting to displaying tooltips at all times?
Background
The chart data is for visualizing our project backlog. Additional details, i.e. Project Name, about each project are in a table.
We previously used google charts, and just included the row number from the table on the bubble so you could match things up.
With Chart.js I only get the bubbles and tooltips.
I've reviewed the following related questions, but the solution they suggested requires having tooltips display at all times. I've got a lot more information in the tooltips and displaying them all the time would significantly clutter the chart.
Can individual bubbles in a chartjs bubble chart have labels?
How to show tooltips always on Chart.js 2

Chart.js doesn't support this directly, but Evert Timberg was very helpful in providing an example Chart.js plugin does exactly this.
From Chart.js Data Labeling Example
// Define a plugin to provide data labels
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
// <---- ADJUST TO DESIRED TEXT --->
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);
});
}
});
}
});
For example, if i just passed in "#22" as the text to render, we get this.

Related

Tooltip overriding the text in chart js

I have created a graph like below using chart.js
The above graph the texts like (Bare, Mounted) I creates this in oncomplete function like
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;
if(dataset._meta[0].controller.index==1){
ctx.fillText(dataset.data[i], model.x-10, model.y+8);
ctx.fillText('Mounted', model.x-25, model.y+38);
ctx.fillText('360 (Available)', model.x-42, model.y-25);
}else{
ctx.fillText(dataset.data[i], 10, model.y+8);
ctx.fillText('Bare', 12, model.y+38);
ctx.fillText($scope.labels[i], 12, model.y-25);
}
}
});
}}
But these values are rendered above the tooltip. How can I avoid this??
Your problem is that onComplete will be called at the end of the animation. That is how onComplete is supposed to work. If there is a tooltip to be drawn, onComplete will be called after the tooltip has been drawn, since drawing the tooltip is part of the animation. This is the reason that your texts are drawn above everything else. What you could do is create (and register) a plugin to draw your texts (ditch the onComplete approach). Look at the docs about creating a plugin. You will have to override one method only (play around to find out which method to override, see some plugin examples, also pay attention to how easing is used) where you should be able to use your current code with just a few changes.

Dygraphs vertical line with label

I need to place a vertical line with a label on my dygraph like the National holiday line in this example - http://www.fusioncharts.com/dev/chart-attributes.html?chart=msline
I have searched google for about 2 hours and can't find any examples. Can someone shoot me an example or put me on the right track? Thanks.
Best practice today is to add highlighted region using underlay callback (example).
try specifying the "underlayCallback" option within your "new Dygraph()" call. Use HTML Canvas context to draw the line.
On creating your graph:
// Graph range on X axis:
var xMin=0, xMax=1;
// horizontal line Y value:
var yValue = 0.5;
new Dygraph(document.getElementById('garph'), data, {
// Graph options
underlayCallback: function(ctx, area, dygraph) {
var xLeft = dygraph.toDomCoords(Min, yValue);
var xRight = dygraph.toDomCoords(Max, yValue);
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.moveTo(xLeft[0], xLeft[1] );
ctx.lineTo(xRight[0], xRight[1]);
ctx.closePath();
ctx.stroke();
}
});
Note this is a very general example, as you haven't shown your own code.

chart.js Line chart with different background colors for each section

Lets say I have a Line chart with mon-fri for 4 weeks.
I want that these 4 weeks are diveded in sections. I want the first monday to friday have a white background color.
The second monday to friday a gray background.
The thirth a white bg again.
And the fourth weeks with monday to friday to have a gray background color.
What Im talking about is the background of the graph.
Is there a way to do this?
Chart.js clears the canvas before drawing (or redrawing) a chart.
We can jump in on this and draw our background once the chart is cleared. Just extend the Line chart and override the clear function in the initialize override.
Preview
Script
Chart.types.Line.extend({
name: "LineAlt",
initialize: function(data){
Chart.types.Line.prototype.initialize.apply(this, arguments);
// keep a reference to the original clear
this.originalClear = this.clear;
this.clear = function () {
this.originalClear();
// 1 x scale unit
var unitX = this.datasets[0].points[1].x - this.datasets[0].points[0].x;
var yTop = this.scale.startPoint;
var yHeight = this.scale.endPoint - this.scale.startPoint;
// change your color here
this.chart.ctx.fillStyle = 'rgba(100,100,100,0.8)';
// we shift it by half a x scale unit to the left because the space between gridline is actually a shared space
this.chart.ctx.fillRect(this.datasets[0].points[5].x - 0.5 * unitX, yTop, unitX * 5, yHeight);
this.chart.ctx.fillRect(this.datasets[0].points[15].x - 0.5 * unitX, yTop, unitX * 5, yHeight);
}
}
});
Then just use LineAlt instead of Line
var myNewChart = new Chart(ctx).LineAlt(data);
Fiddle - http://jsfiddle.net/oe2606ww/
Some people here have requested something that works for later versions, here's my hacked together solution that works on ChartJS 2.7.2 (EDIT: Apr 2020: Also 2.9.3) and could probably be adapted. Chart.types.Line.extend used in the answer above, doesn't seem to be valid in v2.
I managed to figure this out with help from this thread to get the plugin code, and also found this thread useful for gathering co-ordinates of the data points.
With some work this fiddle should allow you to pass the label array keys as start/stop positions via the following code (where 0 and 1 are the keys):
var start = meta.data[0]._model.x;
var stop = meta.data[1]._model.x;
You could loop this, along with the ctx.fillRect function to draw multiple rectangles.
Here's the working fiddle: http://jsfiddle.net/oe2606ww/436/
I combined #potatopeelings's and #v25's solutions for a chart.js v2 solution. It utilizes the format of #potatopeelings's solution, allowing to use an alternate chart type (LineAlt), and the updated implementation from #v25's solution.
Chart.controllers.LineAlt = Chart.controllers.line.extend({
draw: function (ease) {
if (this.chart.config.options.chartArea && this.chart.config.options.chartArea.backgroundColor) {
var ctx = this.chart.chart.ctx;
var chartArea = this.chart.chartArea;
var meta = this.chart.getDatasetMeta(0);
var start = meta.data[1]._model.x;
var stop = meta.data[2]._model.x;
ctx.save();
ctx.fillStyle = this.chart.config.options.chartArea.backgroundColor;
ctx.fillRect(start, chartArea.top, stop - start, chartArea.bottom - chartArea.top);
ctx.restore();
}
// Perform regular chart draw
Chart.controllers.line.prototype.draw.call(this, ease);
}
});
Then you can use the custom chart type just as in #potatopeelings's solution:
var myNewChart = new Chart(ctx, {type: 'LineAlt', data: data});
I'd try a little work around,I'd draw an image with four line each one with width 1px and a different color; then in a CSS sheet define:
canvas {
background-image: url(backgroundimage.jpg);
background-size: contain;
}

Morris.js Donut labels

I'm having an extremely frustrating time trying to move the data text labels from this donut chart to be outside of the center.
http://jsbin.com/ukaxod/144/embed?javascript,live
the xpos and ypos are generated dynamically, and I can't seem to overwrite them with CSS and I can't find what is setting them in JS. A little help would be very appreciated. thanks
The label in the center is placed there by design and cannot be simply changed.
If you look at the source code you can find these lines:
Donut.prototype.redraw = function() {
// ...
cx = this.el.width() / 2;
cy = this.el.height() / 2;
// ...
this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800);
this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14);
// ...
}
It calculates cx/cy so that they point to the center of the chart, and generates 2 labels (for text and value).
You can change the source code, or you can try to find the corresponding text tag in the svg code and change its x and y properties.

How to navigate between points on flot chart?

I would like to build some sort of forward/back pager that will navigate between the points on my chart, highlighting the current point.
The closest example I've seen is something similar to the news legend on google finance charts, https://www.google.ca/finance?q=goog&ei=AD6dUvjOLMi0iAL9Uw
(you can click each news article/event and it will jump in the graph to the relevant point in time on the graph)
Can this be done with Flot and any suggestions on how to do this? Thanks!
Here's a real quick example to demonstrate one approach to this problem. On previous/next button clicks it highlights the previous/next point in the series and adjusts the xaxis so that the hightlighted point stays centered on the screen.
var highlightPoint = 15; // our first highlight
var xmin = 10, xmax = 20; // some arbitrary slice of series
var plot = $.plot("#placeholder", [ d1 ], //initial plot call
{
xaxis:{min: xmin, max: xmax}
});
plot.highlight(0,highlightPoint); // initial highlight
$('#prevPoint').click(function(){
plot.unhighlight(0,highlightPoint); // unhighlight previous selection
highlightPoint -= 1; // move to left
xmin = highlightPoint - 5; // adjust xaxis
xmax = highlightPoint + 5;
plot.getOptions().xaxes[0].min = xmin; // set xaxis into options
plot.getOptions().xaxes[0].max = xmax;
plot.setupGrid(); // refresh chart with new xaxis
plot.draw(); // redraw
plot.highlight(0,highlightPoint); //highlight new point
});
Makes more sense to look at the Fiddle here.

Categories

Resources