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.
Related
I'm trying to make bar chart looks like in picture here:
Here is the result that I got
Maybe someone can suggest, how can I sticked value to xAxis?
Series I want to plot are :
series: [{
name: 'text',
data: [{"color":"#17a78b","y":3.36},
{"color":"#17a78b","y":2.1},{"color":"#17a78b","y":1.67},
{"color":"#17a78b","y":2.07},{"color":"#17a78b","y":-3.89},
{"color":"#17a78b","y":2.73},{"color":"#17a78b","y":2.34},
{"color":"#17a78b","y":2.91},{"color":"#56e8cb","y":4.94},
{"color":"#56e8cb","y":2.99},{"color":"#56e8cb","y":-2.5},
{"color":"#56e8cb","y":3.77}]
}]
Or maybe there is some way to style negative and positive value
You can make it using Highcharts.SVGElement.translate method. Each data label is SVG element which you can translate depend on your needs. This solution is more flexible because you can add more custom logic by analyzing point and label heights. Check demo and code I posted you below.
Code:
chart: {
type: 'column',
events: {
render: function() {
var chart = this,
series = chart.series[0],
offset = 3,
pointHeight,
textHeight,
translateY;
series.points.forEach(function(point) {
textHeight = point.dataLabel.getBBox().height;
pointHeight = point.shapeArgs.height;
if (pointHeight < textHeight) {
translateY = (pointHeight - textHeight / 2) + textHeight + offset;
} else {
translateY = (pointHeight - textHeight / 2) - offset;
}
translateY = (point.y < 0) ? -translateY : translateY;
point.dataLabel.translate(0, translateY);
});
}
}
}
Demo:
https://jsfiddle.net/30bxv9rc/
Api reference:
https://api.highcharts.com/class-reference/Highcharts.SVGElement#translate
https://api.highcharts.com/highcharts/chart.events.render
First set plotOptions.column.stacking to normal so that data labels are displayed inside the columns.
Next, you will need to update each point of data in the series through another function after the chart is rendered. Referring to my example, data points are looped; its value is accessed to check positive or negative; and subsequently verticalAlign and y attributes are updated so that label is displayed according to your requirement.
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.
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.
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;
}
So Im trying to make something where the user is able to drag planets along their orbits and it will continuously update the other planets. Ideally I would like this to work with ellipses too.
So far I can drag an image node with jquery and check/change the coordinates, but i cannot update the position reliably while the user is dragging the object. I know there is an axis and a rectangle containment for draggable but this doesn't really help me.
I have a site for calculating planetary orbits http://www.stjarnhimlen.se/comp/ppcomp.html and a formula i think should help me if i can figure out how to constrain the draggable object with coordinate checks Calculating point on a circle's circumference from angle in C#?
But it seems like there should be an easier way to have a user drag a sphere along a circular track while it updates coords for other spheres
here's what i have so far. It's not much
http://jsfiddle.net/b3247uc2/2/
Html
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
Js
var $newPosX = 100,
$newPosY = 100;
//create image node
var x = document.createElement("IMG");
x.src = "http://upload.wikimedia.org/wikipedia/commons/a/a4/Sol_de_Mayo_Bandera_Argentina.png";
x.width = 100;
x.height = 100;
x.id = "sun";
x.hspace = 100;
x.vspace = 100;
document.body.appendChild(x);
//coords
var text = document.createTextNode($newPosX + " " + $newPosY);
document.body.appendChild(text);
//make sun draggable and update coords
$("#sun").draggable({
drag: function (event, ui) {
$newPosX = $(this).offset().left;
$newPosY = $(this).offset().top;
}
});
//0 millisecond update for displayed coords
setInterval(check, 0);
function check() {
//tries to constrain movement, doesn't work well
/*
if ($newPosX > 300) {
$("#sun").offset({
left: 200
});
}
*/
text.nodeValue = ($newPosX + " " + $newPosY);
}
Edit:
I found this and am trying to modify it to suit my purposes but have so far not had luck.
http://jsfiddle.net/7Asn6/
Ok so i got it to drag
http://jsfiddle.net/7Asn6/103/
This is pretty close to what I want but can be moved without being clicked on directly
http://jsfiddle.net/7Asn6/104/
Ok final edit on this question. This one seems to work well and have fixed my problems. I would still very much like to hear peoples implementation ideas or ideas to make it work smoother.
http://jsfiddle.net/7Asn6/106/