Double donut-like chart with negative values - javascript

I've been asked to do this kind of graph (40,9% and 16,4% are examples, they should indicate something like -6% and 9%):
Any idea on how I can get that kind of result, using a javascript library, if possible (but it is not a must) Highcharts?
Thanks

It's possible with HighCharts, Documentation
e.g.
$(function () {
data = [{
valSecond: 25,
valFirst: 62.5
}];
// Build the data arrays
var secondData = [];
var firstData = [];
for (var i = 0; i < data.length; i++) {
// add second data
secondData.push({
name: "Second",
y: data[i].valSecond,
color: "#00FF00"
});
// add first data
firstData.push({
name: "First",
y: data[i].valFirst,
color:'#FF0000'
});
}
// Create the chart
$('#container').highcharts({
chart: {
type: 'pie'
},
title: {
text: ''
},
plotOptions: {
pie: {
animation: false,
shadow: false,
center: ['50%', '50%']
}
},
tooltip: {
valueSuffix: '%'
},
series: [{
name: 'second',
data: secondData,
size: '30%',
startAngle: 270,
endAngle: 360,
innerSize: '20%'
}, {
name: 'first',
color:'#FFFFFF',
data: firstData,
size: '80%',
startAngle: 0,
endAngle: 225,
innerSize: '60%',
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="width: 600px; height: 400px; margin: 0 auto"></div>
Jsfiddle

In the highcharts you can adapt donut chart http://www.highcharts.com/demo/pie-donut, remove connectors, set useHTML for dataLabels and rotate by css / rotation SVG element. Missing elements can by added by renderer.

Related

How to align a pie chart to the left in highcharts js?

I'm trying to pin a pie chart to the left.
A negative marginLeft and center: ['20%', '50%'] don't give me what i need
since when changing the screen width the position of the chart also changes.
I am using Vue 3 composition api
series: [{
center: ['20%', '90%'],
size: '150%',
innerSize: '65%',
data: [
{
name: 'Valid',
y: 10,
color: '#13CE66'
},
{
name: 'Failed Verification',
y: 5,
color: '#FF4949'
}
],
showInLegend: true
}]
It should be like this:
Use the chart.marginLeft property
Example config:
chart: {
type: 'pie',
width: 400,
height: 200,
marginLeft: -230
},
Example demo:
https://jsfiddle.net/BlackLabel/k52j7m9x/
API Reference:
https://api.highcharts.com/highcharts/chart.marginLeft

pie chart legend overlap with older legend when replace series in highchart

I am trying to update a pie chart but the problem is its overlapping with legends which is causing an issue.
I am remove default series and add new series then old legend is not hide and new legend overlap.
following is my code :
<script src="http://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 300px"></div>
<button id="update">Update chart</button>
$(function () {
$('#container').highcharts({
chart: {
animation: {
duration: 1000
},
type:'pie'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false,
format: '<b>{point.name}</b>: {point.percentage:.1f} %'
},
showInLegend: true
}
},
series: [{
name: 'Brands',colorByPoint: true,
data: [
{ name: 'Data1', y: 60.40,},
{name: 'Data2', y: 39.60,},
]
}]
});
var i = 1;
$('#update').click(function () {
var chart = $('#container').highcharts();
var newData =[{ name: 'ABC', y: 80 },{ name: 'XYZ',
y: 20,}];
while (chart.series.length > 0)
chart.series[0].remove(true);
let series={
name:'new Load',
data:newData
}
chart.addSeries(
series, false
);
chart.redraw()
});
});
That is a regression bug in Highcharts, which is reproted here: https://github.com/highcharts/highcharts/issues/12627 It is already fixed on the master branch.
To workaround use code from master branch or add this plugin:
(function(H) {
H.wrap(H.Point.prototype, 'destroy', function(proceed) {
if (this.legendItem) { // pies have legend items
this.series.chart.legend.destroyItem(this);
}
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
});
}(Highcharts));

Apexchart: Multiple track Colors in Radialbar Chart Multiple

We are trying to make a design like each bar has unique track color instead of common colors in multiple bars, But i didnt find related help in documentation. Kindly someone help me to solve this.
Following is my working code,
var options = {
chart: {
height: 350,
type: 'radialBar',
},
plotOptions: {
radialBar: {
dataLabels: {
track: {
background: '#000000',
startAngle: -135,
endAngle: 135,
},
name: {
fontSize: '22px',
},
value: {
fontSize: '16px',
},
total: {
show: true
}
}
}
},
series: [44, 55, 67, 83],
labels: ['Apples', 'Oranges', 'Bananas', 'Berries'],
}
var chart = new ApexCharts(
document.querySelector("#chart"),
options
);
chart.render();
Thanks in advance,
Multiple track colors in radialBar are not implemented currently but will be available in v2.4.0
You will be able to do it like this
plotOptions: {
radialBar: {
track: {
background: ['#f3f3f3', '#e4e4e4']
}
}
}

Highchart annotation click event doesn't work

I am trying to add a click event on a Highchart annotation but it doesn't work ..
I tried to set the events property on the annotation object like described here :
https://www.highcharts.com/products/plugin-registry/single/17/Annotations
events
mouseup, click, dblclick. this in a callback refers to the annotation
object.
And I don't find anything about annotation events here : https://api.highcharts.com/highcharts/annotations
What I am doing wrong ?
// Data generated from http://www.bikeforums.net/professional-cycling-fans/1113087-2017-tour-de-france-gpx-tcx-files.html
var elevationData = [
[0.0, 225],
[0.1, 226],
[0.2, 228],
[0.3, 228],
[0.4, 229],
[0.5, 229],
[0.6, 230],
[0.7, 234],
[0.8, 235],
[0.9, 236],
[1.0, 235],
];
// Now create the chart
Highcharts.chart('container', {
chart: {
type: 'area',
zoomType: 'x',
panning: true,
panKey: 'shift',
scrollablePlotArea: {
minWidth: 600
}
},
title: {
text: '2017 Tour de France Stage 8: Dole - Station des Rousses'
},
subtitle: {
text: 'An annotated chart in Highcharts'
},
annotations: [{
labelOptions: {
backgroundColor: 'rgba(255,255,255,0.5)',
verticalAlign: 'top',
y: 15
},
labels: [{
point: {
xAxis: 0,
yAxis: 0,
x: 0.9,
y: 235,
},
text: 'Arbois',
}],
events:{
click: function(e){alert('test');}
}
}],
xAxis: {
labels: {
format: '{value} km'
},
minRange: 5,
title: {
text: 'Distance'
}
},
yAxis: {
startOnTick: true,
endOnTick: false,
maxPadding: 0.35,
title: {
text: null
},
labels: {
format: '{value} m'
}
},
tooltip: {
headerFormat: 'Distance: {point.x:.1f} km<br>',
pointFormat: '{point.y} m a. s. l.',
shared: true
},
legend: {
enabled: false
},
series: [{
data: elevationData,
lineColor: Highcharts.getOptions().colors[1],
color: Highcharts.getOptions().colors[2],
fillOpacity: 0.5,
name: 'Elevation',
marker: {
enabled: false
},
threshold: null
}]
});
#container {
max-width: 800px;
min-width: 380px;
height: 400px;
margin: 1em auto;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/annotations.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<div id="container" style="height: 400px; min-width: 380px"></div>
EDIT :
I resolved my problem by getting the annotation.group element and assign it a event handler.
for(var annotation in chart.annotations){
var element = chart.annotations[annotation].group.element;
element.addEventListener("click",function(e){alert('here I am');});
}
It not supported, but very simple and quick in implementation. You need to do the wrap on the initLabel function, and after calling proceed, just assign the events defined in your Annotation / label object. Here is the example code with handling click event:
(function(H) {
H.wrap(H.Annotation.prototype, 'initLabel', function(proceed, shapeOptions) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
var label = this.labels[this.labels.length - 1]
var annotation = label.annotation
if (label && annotation) {
label.element.onclick = label.options.events.click || annotation.options.events.click
}
})
})(Highcharts)
It assigns the event defined in your label object, but if it's undefined, it takes the function definition directly from Annotation object for all labels.
Additionally, you can read more about Highcharts.wrap() function here: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts
Here is the example of using it: http://jsfiddle.net/ew7ufnjb/
[EDIT]
Wrap method is no longer necessary since v7.0. Just delete the wrap method and keep the event definition from general Annotation object.
Live example: http://jsfiddle.net/rgm3puL8/

c3 bar graph align tick values with non-centered ticks

I'm trying to push the values on the x category axis to be on the sides of the bars, not in the middle. Apparently it is possible to put the ticks there, but can values go under the ticks as well?
var chart;
chart = c3.generate({
data: {
columns: [
['data', 30, 200, 100, 400, 150, 250]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.98
}
},
axis: {
x: {
type: 'category',
categories: [10, 50, 100, 500, 2000, 5000],
tick: {
centered: false
}
}
},
legend: {
show: false
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<div id="chart" class="c3" style="max-height: 280px; position: relative;"></div>
It's not the prettiest answer, and the last label gets chopped off (you'll have to investigate c3's padding options), but these 2 lines after you've rendered the chart do the trick:
// use c3's internal x scale to get the width of one bar
var width = chart.internal.x(1) - chart.internal.x(0);
// shuffle all the tick label tspans along by half a bar's width
d3.select(".c3-axis").selectAll(".tick text tspan").attr("dx", width/2);
var chart;
chart = c3.generate({
data: {
columns: [
['data', 30, 200, 100, 400, 150, 250]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.98
}
},
axis: {
x: {
type: 'category',
categories: [10, 50, 100, 500, 2000, 5000],
tick: {
centered: false
}
}
},
legend: {
show: false
}
});
var width = chart.internal.x(1) - chart.internal.x(0);
d3.select(".c3-axis").selectAll(".tick text tspan").attr("dx", width/2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<div id="chart" class="c3" style="max-height: 280px; position: relative;"></div>

Categories