ChartJS: Get individual values minus another value in the custom legend - javascript

I have a Pie chart with multiple rings and created a Custom Legend function with below code:
var data = [{
labels: ["Mumbai", "Chennai", "Hyderabad", "Bangalore"],
data: [30, 32, 38, 50],
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}, {
labels: ["India 2018", "India 2017"],
data: [450, 400],
backgroundColor: [
"#92d400",
"#95a455"
],
borderColor: "#fff"
}];
The first ring represents four individual cities and center rings represents Country total value, but not the sum total of four cities.
I want to show this custom legend:
Mumbai: 30
Chennai: 32
Hyderabad: 38
Bangalore: 50
India: 450
Rest of Mumbai: 420
Rest of Chennai: 418
Rest of Hyderabad: 412
Rest of Bangalore: 400
First set is individual data values.
Second set is (India value - City value)
Below is the custom legend function:
legendCallback: function (chart) {
var text = [];
text.push('<ul class="list-inline my-0 text-center ' + chart.id + '-legend text-secondary">');
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' +
chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">' + chart.data.datasets[0].labels[i] + ': ' + chart.data.datasets[0].data[i] +'</span>');
}
text.push('</li>');
}
text.push('</ul>');
text.push('</ul>');
text.push('<ul class="list-inline">');
text.push('<li class="list-inline-item">Rest of Mumbai: 420</li>');
text.push('<li class="list-inline-item">Rest of Chennai: 418</li>');
text.push('<li class="list-inline-item">Rest of Hyderabad: 412</li>');
text.push('<li class="list-inline-item">Rest of Bangalore: 400</li>');
text.push('</ul>');
return text.join('');
},
I am able to show individual label values but not the Rest of the *** labels value.
Here is the JSFiddle (https://jsfiddle.net/kingBethal/aubsjn4c/11/)
Update# 1
Below is the table represents the values in the Pie and desired Custom legend output:
Custom legend will show (India 2018 minus individual city) values.
An example:
Rest of Mumbai = India 2018 (450) - Mumbai (30) = 420

just need to reference the second dataset and subtract the city values...
here, you're building the first legend...
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' + chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">' + chart.data.datasets[0].labels[i] + ': ' + chart.data.datasets[0].data[i] +'</span>');
}
text.push('</li>');
}
to build the second, use the same code, but reference the second dataset and subtract the city value...
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' + chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">Rest of ' + chart.data.datasets[0].labels[i] + ': ' +
(chart.data.datasets[1].data[0] - chart.data.datasets[0].data[i]) + // <-- second dataset = datasets[1] and india 2018 = data[0]
'</span>');
}
text.push('</li>');
}
see following working snippet...
var data = [{
labels: ["Mumbai", "Chennai", "Hyderabad", "Bangalore"],
data: [30, 32, 38, 50],
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}, {
labels: ["India 2018", "India 2017"],
data: [450, 400],
backgroundColor: [
"#92d400",
"#95a455"
],
borderColor: "#fff"
}];
var options = {
cutoutPercentage: 35,
legendCallback: function (chart) {
var text = [];
text.push('<ul class="list-inline my-0 text-center ' + chart.id + '-legend text-secondary">');
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' + chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">' + chart.data.datasets[0].labels[i] + ': ' + chart.data.datasets[0].data[i] +'</span>');
}
text.push('</li>');
}
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' + chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">Rest of ' + chart.data.datasets[0].labels[i] + ': ' +
(chart.data.datasets[1].data[0] - chart.data.datasets[0].data[i]) + // <-- second dataset = datasets[1] and india 2018 = data[0]
'</span>');
}
text.push('</li>');
}
text.push('</ul>');
return text.join('');
},
legend: {
display: false
},
plugins: {
datalabels: {
color: '#ffffff'
}
},
tooltips: {
callbacks: {
label: function (item, data) {
var label = data.datasets[item.datasetIndex].labels[item.index];
var value = data.datasets[item.datasetIndex].data[item.index];
var allData = data.datasets[item.datasetIndex].data;
var tooltipData = allData[item.index];
return label + ': ' + tooltipData;
}
},
titleFontSize: 14,
bodyFontSize: 12
}
};
var ctx = document.getElementById("my-chart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
datasets: data
},
options: options
});
$('#legend').html(myChart.generateLegend());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="my-chart"></canvas>
<div id="legend"></div>

Related

JS and Leaflet : Display the markers little by little in slider js

I need to display the markers little by little according to their date of appearance, here the JS code:
function initialize() {
var map = L.map('mapid').setView([48.862162, 2.345818], 11);
var couche1 = L.tileLayer('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
attribution: 'crédits : <a href= » http://osm.org/copyright »>OpenStreetMap</a> contributeur',
maxZoom: 19
});
map.addLayer(couche1);
var colorLayer = L.tileLayer('http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg', {
attribution: '© <a href= » http://osm.org/copyright »>OpenStreetMap</a>',
maxZoom: 19
});
map.addLayer(colorLayer);
var arrondissement = $.getJSON("arrondissements.geojson", function (dataArrondissements) {
L.geoJson(dataArrondissements,
{
style: function (feature) {
return { color: '#046380', weight: 1, fillColor: '#4BB5C1', fillOpacity: .6 };
},
onEachFeature: function (feature, layer) {
layer.bindPopup('<b><u>Quel arrondissement ?</u></b><br><b> Arrondissement n° </b>' + feature.properties.c_ar)//affiche le numéro de l'arrondissement selon le fichier arrondissements.geojson
}
}).addTo(map);
});
var borne = $.getJSON("borne.geojson", function (coordonneesxy)
{
var iconeborne = L.icon({
iconUrl: 'img/borne.png',
iconSize: [40, 40]
});
L.geoJson(coordonneesxy, {
pointToLayer: function (feature, latlng) {
var marker = L.marker(latlng, { icon: iconeborne });
marker.bindPopup('<b><u>Description de la borne</u></b><br>'//titre
// infos de la borne à afficher :
+ '<b>Nom : </b>' + feature.properties.nom_station + '<br>'
+ '<b>statut : </b>' + feature.properties.statut_pdc + '<br>'
+ '<b>adresse : </b>' + feature.properties.adresse_station + '<br>'
+ '<b>Puissance : </b>' + feature.properties.puissance_nominale + '<br>'
+ '<b>Mise en service le : </b>' + feature.properties.date_mise_en_service + '<br>'
+ '<b>Paiement CB : </b>' + feature.properties.paiement_cb + '<br>'
+ '<b>Paiement autre : </b>' + feature.properties.paiement_autre + '<br>'
+ '<b>Infos : </b>' + feature.properties.observations + '<br>'
+ '<b>Accesibilite PMR : </b>' + feature.properties.accessibilite_pmr + '<br>'
+ '<b>Prise type 2 : </b>' + feature.properties.prise_type_2
);
return marker;
}
}).addTo(map);
});
var baseLayers = {
'OpenStreetMap': couche1,
'color': colorLayer
};
L.control.layers(baseLayers).addTo(map);
}
var dateSlider = document.getElementById("noUiSlider"); var monthsOld = [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Septembre", "Octobre", "Novembre", "Décembre" ];
var months = [ "01/", "02/", "03/", "04/", "05/", "06/", "07/", "08/", "09/", "10/", "11/", "12/" ];
var initial = "2019-08-01"; var final = "2022-12-23";
function timestamp(str) { return new Date(str).getTime(); }
function formatDate(date) { console.log( "Format: ", monthsOld[date.getMonth()] + " " + date.getFullYear().toString() );
function formatDate(date) { console.log( "Format: ", monthsOld[date.getMonth()] + " " + date.getFullYear().toString() );
return ( monthsOld[date.getMonth()] + " " + date.getFullYear().toString() ); }
function formatDate2(date) { console.log( "Format: ", months[date.getMonth()] + " " + date.getFullYear().toString() );
return ( months[date.getMonth()] + " " + date.getFullYear().toString() ); }
noUiSlider.create(dateSlider, {
range: { min: timestamp(initial), max: timestamp(final) }, connect: true,
step: 50 * 30 * 60 * 60 * 1000,
start: [timestamp(initial), timestamp(final)],
pips: { mode: "steps", stepped: true, density: 24, format: { to: function (value) { if (value == 0) return 0; return formatDate2(new Date(value)); }, from: function (value) { return timestamp(value); } } } });
var dateValues = [ document.getElementById("datestart"), document.getElementById("dateend") ];
dateSlider.noUiSlider.on("update", function (values, handle) { console.log("Value: ", values[handle]); dateValues[handle].innerHTML = formatDate(new Date(+values[handle])); });
I don't know how to display the markers little by little on a leaflet.js map, I have a Nouislider slider and a map with stations displayed on it.
//Data in geojson found here :
=> https://opendata.paris.fr/explore/dataset/arrondissements/
=> https://opendata.paris.fr/explore/dataset/belib-points-de-recharge-pour-vehicules-electriques-donnees-statiques/
I used the data above in GeoJson

Fusioncharts Real-time Line anchorbgclor

I want to use anchorBgColor attribute for Real-time Line chart.
Real-time Line chart.
function updateData() {
var t = new Date(),
date =
t.getHours() + ":" + t.getMinutes() + ":" + t.getSeconds(),
val = Math.floor(Math.random() * (7800 - 7200 + 1)) + 7200,
strData = "&label=" + date + "&value=" + val;
// Feed it to chart.
chartRef.feedData(strData);
}
Could you recommend how to change anchorBgColor for this chart?
If you are wanting to have all the points the same color all you have to do is include the anchorBgColor property in the chart object
{
...
dataSource: {
chart: {
...
anchorBgColor: "#26aa5a"
}
}
}
If you want points to change colors as you add them you have manipulate the chart data object and use setJSONData rather than using the feedData method.
<div id="chart-container">FusionCharts will render here</div>
FusionCharts.ready(function() {
var chartObj = new FusionCharts({
type: 'line',
renderAt: 'chart-container',
id: 'myChart',
width: '500',
height: '300',
dataFormat: 'json',
dataSource: {
"chart": {
"theme": "fusion",
"anchorRadius": "6",
"theme": "fusion"
},
"data": []
}
});
chartObj.render();
function pushNewPoint() {
var t = new Date(),
date =
t.getHours() + ":" + t.getMinutes() + ":" + t.getSeconds(),
val = Math.floor(Math.random() * (7800 - 7200 + 1)) + 7200,
randomColor = Math.floor(Math.random()*16777215).toString(16)
newEntry = {
label: date,
value: val,
anchorBgColor: "#" + randomColor
}
chartData = chartObj.getChartData('json')
chartData.data.push(newEntry)
chartObj.setJSONData(chartData)
}
var counter = 0;
var i = setInterval(function(){
pushNewPoint()
counter++;
if(counter === 10) {
clearInterval(i);
}
}, 1000);
});
Example can be seen here

highcharts from HTML table does not getting the x axis key

I am using a highcharts to draw chart from HTML table , my problem is i want to custom the tooltip but the "this.x" or "this.key" returned as decimal number not as string, how can I get the x axis value as it is??
and that's my code:
Highcharts.chart('ChartContainer', {
data: {
table: 'tblData'
},
chart: {
type: 'line'
},
title: {
text: ''
},
yAxis: {
allowDecimals: false,
title: {
text: ''
}
},
tooltip: {
useHTML: true,
formatter: function () {
return GetCustomTooltip(this.series.name, this.y, firstSeriesToolTip, firstTooltipTitle, secondTooltipTitle, this.zvalue);
}
}
});
function GetCustomTooltip(xvalue, yvalue, TooltipArray, firstTooltipTitle, secondTooltipTitle, zvalue, thirdTooltipTitle) {
var tooltipMessage = '';
for (var i = 0; i < TooltipArray.length; i++) {
if (TooltipArray[i][0]== xvalue) {
tooltipMessage += '<b>' + xvalue + '</b><br>';
tooltipMessage += firstTooltipTitle + ': ' + '<b>' + yvalue + '</b><br>';
if (secondTooltipTitle != null)
tooltipMessage += secondTooltipTitle + ': ' + '<b>' + TooltipArray[i][1] + '</b><br>';
if (thirdTooltipTitle != null)
tooltipMessage += thirdTooltipTitle + ': ' + '<b>' + TooltipArray[i][3] + '</b><br>';
break;
}
}
return tooltipMessage;
}
and the table I build it dynamically before draw the chart.
I got the right values when I change the xAxis type to category

Obtaining x-axis values in c3.js to customize the tooltip?

I'm trying to edit the tooltip in a c3 line-chart. Specifically, I need to access the current x-value within the chart.tooltip.format.value function. However, the function is not passed the x-value explicitly.
var chart = c3.generate({
tooltip: {
format: {
value: function (value, ratio, id, index) {
return value;
}
}
},
data: {
x: 'YEAR',
xFormat: '%Y',
url: myURL',
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y'
}
},
},
});
You can use the tooltip's contents property to create a custom tooltip, and in there you can access the X value via: d[0].x.
Edit: use d[0].x.getFullYear() to retrieve only the year part of the date (it's a time series so C3 internally stores the supplied year as a javascript date object)
Here's code I've taken from this discussion https://github.com/c3js/c3/issues/444, and modified:
function tooltip_contents(d, defaultTitleFormat, defaultValueFormat, color) {
var $$ = this, config = $$.config, CLASS = $$.CLASS,
titleFormat = config.tooltip_format_title || defaultTitleFormat,
nameFormat = config.tooltip_format_name || function (name) { return name; },
valueFormat = config.tooltip_format_value || defaultValueFormat,
text, i, title, value, name, bgcolor;
// You can access all of data like this:
//console.log($$.data.targets);
for (i = 0; i < d.length; i++) {
if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
// to exclude
//if (d[i].name === 'data2') { continue; }
if (! text) {
title = 'MY TOOLTIP # ' + d[0].x.getFullYear(); // SHOW X-VALUE, year only (given it is a time series)
text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
}
name = nameFormat(d[i].name);
value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
text += "<td class='value'>" + value + "</td>";
text += "</tr>";
}
return text + "</table>";
}
var chart = c3.generate({
data: {
x: 'year',
xFormat: '%Y',
columns: [
['year', '1970', '1975', '1980', '1985', '1990'],
['data1', 100, 200, 150, 300, 200],
['data2', 400, 500, 250, 700, 300],
]
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y'
}
},
},
tooltip: {
contents: tooltip_contents
}
});
My fiddle, showing the current x-value: http://jsfiddle.net/w7h385h3/5/

Tooltip stacked column with 3 values array

I have a json code like this
[[1385420403000,9.86,6.91],[1385506802000,11.89,6.57],[1385593203000,14.11,10.58],[1385679602000,9.1,8.9],[1385766003000,13.59,7.53],[1385852402000,10.68,6.69],[1385938803000,11.03,10.52],[1386025202000,11.16,8.18],[1386111603000,12,5.76]]
I want to display the 3rd value (this.z) on tooltip with highstock.
This is my code to select data for the stacked column.
var date = [],
hp = [],
hc = [],
datalength = data.length;
for (i = 0; i < datalength; i ++) {
date.push([
data[i][0], // the date
]);
hp.push([
data[i][0], // the date
data[i][1], // hp
]);
hc.push ([
data[i][0], // the date
data[i][2], //hc
])
}
My tooltip :
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.75)',
style: {
color: '#F0F0F0'
},
formatter: function() {return ' ' +
Highcharts.dateFormat('%A %d %b %Y', this.x) +""+'<br />'+
'HP : ' + this.y + " kwh"+'<br />' +
'Prix HP : ' + Highcharts.numberFormat((this.y*0.1467),2)+" €" +'<br />'+
'HC : ' + this.z + " kwh"+'<br />' +
'Prix HC: ' + Highcharts.numberFormat((this.z*0.1002),2)+" €"+'<br />' +
'Prix total : ' + Highcharts.numberFormat(((this.y*0.1467)+(this.z*0.1002)),2)+" €";
},
},
And the series :
series: [{
type: 'column',
name: 'HP',
data: hp,
},{
type: 'column',
name: 'HC',
data: hc,
}]
this.z is undefined. How can i replace it ?
To do this you would need to make a 3D set of data such that hp would look like:
{
type: 'column',
name: 'HP',
data: [
{x:1385420403000, y:9.86, note:6.91},
{x:1385506802000, y:11.89, note:6.57},
{x:1385593203000, y:14.11, note:10.58},
....
]
}
To do that you would set you hp filler loop to look something like:
hp.push([
data[i][0], // the date
data[i][1], // hp
data[i][2] // the note item.
]);
If you look at your hp.push code you have a dangling comma and you are never actually looking at the 3rd element in your array.
Then in your tooltip you would reference this.note.

Categories

Resources