canvas fill text vanishes when hovering over chartjs pie chart - javascript

I am using a doughnut chart from chartjs, and in the center of this canvas I am filling two lines of text. These show up fine after the initial animation, but when I hover over the doughnut, a tool tip shows up for the relevant element (which is expected), but the fill text vanishes. Any reason why this might be happening and how I can rectify it ?
here is the code I am using to generate the text on the canvas
var pieChart = document.getElementById("pieChart").getContext("2d");
new Chart(pieChart).Doughnut(pieData, {percentageInnerCutout : 80, animationEasing: "easeOutQuart", onAnimationComplete: function() {
pieChart.fillStyle = 'black'
pieChart.font = "50px Roboto";
pieChart.textAlign = "center";
pieChart.fillText(distributionChartData[3]+" %", 135, 120);
pieChart.font = "20px Roboto";
pieChart.fillText((distributionChartData[0]+distributionChartData[1]+distributionChartData[2])+" Responses", 135, 160);
}
});
Here is an image of the chart after initial load
this is the image after hover

Actually you can do this with a simple extension of the chart type you are using and moving your draw code to inside the draw override
Preview
Code
Chart.types.Doughnut.extend({
name: "DoughnutAlt",
draw: function () {
Chart.types.Doughnut.prototype.draw.apply(this, arguments);
this.chart.ctx.textBaseline = "middle";
this.chart.ctx.fillStyle = 'black'
this.chart.ctx.font = "50px Roboto";
this.chart.ctx.textAlign = "center";
this.chart.ctx.fillText(distributionChartData[3] + " %", 135, 120);
this.chart.ctx.font = "20px Roboto";
this.chart.ctx.fillText((distributionChartData[0] + distributionChartData[1] + distributionChartData[2]) + " Responses", 135, 160);
}
});
var pieChart = document.getElementById("pieChart").getContext("2d");
new Chart(pieChart).DoughnutAlt(pieData, {
percentageInnerCutout: 80, animationEasing: "easeOutQuart"
});
Fiddle - http://jsfiddle.net/p979zyLj/

ChartJS will redraw itself as needed (for example when displaying tooltips), so you must redraw your "% and responses" text whenever ChartJS refreshes (redraws) the chart.
You can set ChartJS's 'onAnimationComplete' callback to draw your call your "% and responses" text when ChartJs has completed it's own drawing and animating.
[ Addition: ]
I've taken a look at the ChartJS source code and the Issues on Github.
There is currently no way within the ChartJS API to trigger redraws of your custom text (your "% and responses") after a tooltip closes.
One workaround would be to use CSS to place a div with your "% and responses" over the chart.

I think you can set option: {animation: false} on your Chartjs settings to solve 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.

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

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.

Use transparent stroke color with chartjs pie chart

Following the chart.js docs, I try to draw a transparent stroke line in a pie chart:
var options = { segmentStrokeColor: "rgba(255,255,255,0)" };
or
var options = { segmentStrokeColor: "transparent" };
But the stroke line is not drawn with these values. Of course it works if I use any other color.
The border or segment stroke is drawn over the sectors. So if you set the color to transparent, you won't see any gap between the sectors (I assume that is what you are expecting). It'll be almost as if you set storkewidth to 0.
It's pretty obvious if you set the segmentStrokeWidth to a high enough value and set a translucent value i.e. something like
var myPieChart = new Chart(ctx).Pie(data, {
segmentStrokeWidth: 20,
segmentStrokeColor: "rgba(255, 255, 255, 0.4)"
});
Contrast this fiddle - http://jsfiddle.net/tabb8gy0/ with this - http://jsfiddle.net/m2k62fgp/

KineticJS: How can I include custom canvas shapes in a toDataURL function

My problem started with the version 5 of KineticJS, before that it was not a problem. Native KineticJS shapes such as squares and circles can be saved to an image file using the stage.toDataURL function. But it doesn't work for non-Kinetic shapes drawn with normal canvas methods such as beginPath(); and canvas.fill(); (version 4 did this fine). The following code draws two rectangles, one red and one blue. The red is custom, the blue is a native kinetic rectangle.
<body>
<div id="container"></div>
<button id="save">
Save as image
</button>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.2.min.js"> </script>
<script>
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var box = new Kinetic.Rect({
x: 400,
y: 80,
width: 100,
height: 50,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
layer.add(box);
stage.add(layer);
var canvas = layer.getCanvas().getContext('2d');
canvas.beginPath();
canvas.setAttr('strokeStyle', 'black');
canvas.setAttr('fillStyle', '#FF2222');
canvas.setAttr('lineWidth', 8);
canvas.rect(50,80,100,50);
canvas.stroke();
canvas.fill();
document.getElementById('save').addEventListener('click', function() {
stage.toDataURL({
callback: function(dataUrl) {
window.location.href = dataUrl;
}
});
}, false);
</script>
</body>
Both shapes appear, but only the blue rectangle appears in the image generated by the toDataURL function. The way they are drawn has changed in KineticJS 5, where you set attributes for fillStyle etc. so I'm thinking that may have something to do with it, or maybe the fact that the custom shape is added after the layer is added to the stage...
You are correct, between recent versions much has changed, and this has probably broken something in your drawing function.
You should consult the official docs on each item, but basically a custom shape has slightly updated properties... first of all "StrokeStyle" is no longer a valid property. Just use 'stroke'. Same thing with FillStyle.
Also -- 'dashArray' is no longer valid, now it's just 'dash' -- so I'm sure there are more things that changed that I'm not recalling... right, such as 'lineWidth' is now 'strokeWidth'...
Also -- the way you show or don't show strokes and fills has changed... yep, pretty much most of the way you used to do it has been changed slightly. 'drawFunc' is now 'sceneFunc' also...
var ctx = layer.getContext();
var customShape01 = new Kinetic.Shape({
sceneFunc: function(ctx) {
ctx.beginPath();
ctx.moveTo(162.1, 213.8);
ctx.bezierCurveTo(162.1, 213.8, 180.7, 215.3, 193.5, 214.5);
ctx.bezierCurveTo(205.8, 213.7, 221.8, 212.3, 222.8, 221.4);
ctx.bezierCurveTo(222.9, 221.7, 222.9, 222.0, 222.9, 222.3);
ctx.bezierCurveTo(222.9, 232.4, 204.6, 232.7, 192.0, 227.1);
ctx.bezierCurveTo(179.4, 221.5, 163.1, 213.8, 162.1, 213.8);
ctx.closePath();
ctx.fillStrokeShape(this);
},
id: 'customShape01',
fill: 'rgb(255, 0, 255)',
stroke: 'black',
strokeWidth: 2,
lineJoin: 'round',
dash: [5,5],
dashEnabled: 'true',
strokeEnabled: 'true'
});
check out a full working sample (you'll have to allow popups).
http://jsfiddle.net/axVXN/1/

Donut / Radial Chart with Raphael

Im a beginner to Raphael. Can anyone show me how I can do a donut/radial chart, with animation, similar to these.
http://dribbble.com/shots/670348-Segment-Graphs
Im working at it now. So far Ive got this far. I will update as I make progress. My sumbling block right now is animating a change in color for the outer ring.
window.onload = function () {
// Creates canvas 320 × 200 at 10, 50
var paper = Raphael(10, 50, 320, 200);
// Creates circle at x = 50, y = 40, with radius 10
var circle1 = paper.circle(50, 40, 40);
var circle2 = paper.circle(50, 40, 20);
circle2.attr("fill", "#fff");
circle2.attr("stroke", "#fff");
circle1.attr("fill", "#336699");
circle1.attr("stroke", "#fff");
}
Credits:
On the raphael website there is an example that uses arcs. There is another question on stackoverflow with a similar topic: drawing centered arcs in raphael js. The accepted answer there has a simplified and commented version of the most important parts of the code, plus there is a jsfiddle link showing the code in action: http://jsfiddle.net/Bzdnm/2/
So what I did: I took the code from the linked question, combined it with eve, another javascript library made by the creator of RaphaelJS and what I got was this: http://jsfiddle.net/cristighenea/aP7MK/
At a glance:
1.after the arc is created we rotate it 180 degrees and begin animating it:
theArc.rotate(180, 100, 100).animate({
arc: [100, 100, amount, 100, 40]
}, 1900, function(){
//animation finish callback goes here
});
2.using eve we bind an event to *raphael.anim.frame.**
3.each time the event is fired we update the text in the middle with the new value of the arc
If you have any questions let me know

Categories

Resources