Override the default format for some legend items in ChartJS - javascript
Wanting to use ChartJS to generate a complex combination graph. All working well with the exception of being able to control the formatting of the legend.
Trying to achieve something like this:
desired chart display
The code I have for this is below. Have tried using the generateLabels function to override but with no success. I'd settle for being able to set the background color of the boxes in the legend to be clear so that the dashed lines are more obvious.
# quickchart-python https://github.com/typpo/quickchart-python
from quickchart import QuickChart
qc = QuickChart()
qc.width = 600
qc.height = 400
# Config can be set as a string or as a nested dict
qc.config = """{
"type": "line",
"data": {
"labels": [
"2015-16",
"2016-17",
"2017-18",
"2018-19",
"2019-20",
"2020-21",
"2021-22",
"2022-23",
"2023-24",
"2024-25",
"2025-26",
"2026-27",
"2027-28",
"2028-29",
"2029-30",
"2030-31",
"2031-32",
"2032-33",
"2033-34",
"2034-35",
"2035-36",
"2036-37",
"2037-38",
"2038-39",
"2039-40",
"2040-41",
"2041-42",
"2042-43",
"2043-44",
"2044-45",
"2045-46",
"2046-47",
"2047-48",
"2048-49"
],
"datasets": [
{
"label": "Emissions (actual)",
"borderColor": "rgb(192,0,0)",
"backgroundColor": "rgb(192,0,0)",
"pointBorderWidth": 0,
"pointBackgroundColor": "rgb(192,0,0)",
"pointStyle":"line",
"pointRadius": 0,
"fill": false,
"data": [
2250,2230,2195,2185,2170,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
],
"yAxisID": "y"
},
{
"label": "Emissions (projected)",
"borderColor": "rgb(192,0,0)",
"borderDash": [4,4],
"backgroundColor": "rgb(0,0,0)",
"pointBorderWidth": 0,
"pointBackgroundColor": "rgb(192,0,0)",
"pointStyle":"line",
"pointRadius": 0,
"fill": false,
"data": [
,,,,2170,2170,2170,2170,2170,2190,2200,2210,2210,2210,2210,2210,2210,2210,
2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210,2210
],
"yAxisID": "y"
},
{
"label": "Sequestration (estimated)",
"borderColor": "rgb(0,112,192)",
"backgroundColor": "rgb(0,112,192)",
"pointBorderWidth": 2 ,
"pointBackgroundColor": "rgb(0,112,192)",
"pointStyle":"line",
"pointRadius": 0,
"fill": false,
"data": [
3197,3159,3121,3083,3008,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
],
"yAxisID": "y"
},
{
"label": "Sequestration (projected)",
"borderColor": "rgb(0,112,192)",
"borderDash": [4,4],
"backgroundColor": "rgb(0,112,192)",
"pointBorderWidth": 2,
"pointBackgroundColor": "rgba(0,112,192,0.1)",
"pointStyle":"line",
"pointRadius": 0,
"fill": false,
"data": [
,,,,3008,2970,2932,2894,2856,2818,2780,2742,2704,2666,2628,2590,2552,
2514,2476,2438,2400,2362,2324,2286,2248,2210,2172,2134,2096,2058,2020,
1982,1944,1906
],
"yAxisID": "y"
},
{
"label": "Cumulative balance (actual)",
"borderColor": "rgb(112,173,71)",
"backgroundColor": "rgb(112,173,71)",
"pointBorderWidth": 0,
"pointBackgroundColor": "rgb(112,173,71)",
"pointStyle":"line",
"pointRadius": 0,
"fill": true,
"data": [
947,1876,2802,3700,4538,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
],
"yAxisID": "y1"
},
{
"label": "Cumulative balance (projected)",
"borderColor": "rgba(112,173,71,0.4)",
"backgroundColor": "rgba(112,173,71,0.6)",
"pointBorderWidth": 0,
"pointBackgroundColor": "rgba(112,173,71,0.6)",
"pointStyle":"line",
"pointRadius": 0,
"fill": true,
"data": [
,,,,4538,5338,6100,6824,7510,8138,8718,9250,9744,10200,10618,10998,11340,11644,
11910,12138,12328,12480,12594,12670,12708,12708,12670,12594,12480,12328,12138,
11910,11644,11340
],
"yAxisID": "y1"
}
]
},
"options": {
"stacked": false,
"legend" : {
display: true,
position: 'bottom',
generateLabels(chart) {
return {
fillStyle: "rgb(255,255,255)"
}
}
},
"title": {
"display": false,
"text": "Chart.js Line Chart - Multi Axis"
},
"scales": {
"xAxes":[{
"ticks": {"fontFamily": "Calibri",
"fontSize": 9}
}],
"yAxes": [
{
"id": "y",
"type": "linear",
"display": true,
"position": "left",
"ticks": {
"min": 1000,
"max": 3500,
"stepSize": 500,
"fontFamily": "Calibri",
"fontSize": 9
},
"scaleLabel": {
"display": true,
"labelString": "Emissions and Sequestration - tCO2e per year",
"fontFamily": "Calibri",
"fontSize": 11
}
},
{
"id": "y1",
"type": "linear",
"display": true,
"position": "right",
"gridLines": {
"drawOnChartArea": false
},
"ticks": {
"min": 0,
"max": 14000,
"stepSize": 2000,
"fontFamily": "Calibri",
"fontSize": 9
},
"scaleLabel": {
"display": true,
"labelString": "Cumulative carbon balance - tCO2e",
"fontFamily": "Calibri",
"fontSize": 11
}
}
]
}
}
}"""
# You can get the chart URL...
print(qc.get_url())
# Get the image as a variable...
image = qc.get_image()
# Or write the chart to a file
qc.to_file('mychart.png')
This is because you putted the generateLabels function in the root of the legend options while it needs to be nested within the labels key like so:
options: {
legend: {
labels: {
generateLabels: (chart) => {
// Implementation
}
}
}
}
Documentation: https://www.chartjs.org/docs/2.9.4/configuration/legend.html#legend-label-configuration
Related
Fill graph area with a gradient in HighChart
I'm using highcharts and react-highcharts to display some graph in my application. Ideally I would like to color the area of the graph with some gradient, from the documentation and this example the option that I should add is this: plotOptions: { area: { fillColor: { linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, stops: [ [0, Highcharts.getOptions().colors[0]], [1, Highcharts.color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')] ] } } }, I'm trying to replicate the same with the configuration of my graph but it doesn't work, the graph looks exactly the same as if there was no fillColor option added. Here's the config of my graph: { "title": { "text": "" }, "chart": { "height": 500, "animation": false, "events": {} }, "legend": { "enabled": true, "align": "center", "verticalAlign": "bottom", "useHTML": true, "y": 15 }, "navigator": { "enabled": true, "adaptToUpdatedData": false, "handles": { "enabled": false }, "outlineWidth": 0, "maskFill": "rgba(0, 0, 0, 0)", "series": { "type": "areaspline", "color": "#4572A7", "fillOpacity": 0.05, "dataGrouping": { "smoothed": true }, "lineWidth": 1, "marker": { "enabled": false }, "data": [ [ 1623200400000, 1.3675397235722446 ], [ 1623286800000, 1.3482760115327748 ], [ 1623373200000, 1.3546129384275694 ], [ 1623632400000, 1.3414434698775963 ], [ 1623718800000, 1.3312870572603575 ], [ 1623200400000, 1.3675397235722446 ], [ 1623286800000, 1.3482760115327748 ], [ 1623373200000, 1.3546129384275694 ], [ 1623632400000, 1.3414434698775963 ], [ 1623718800000, 1.3312870572603575 ] ] }, "max": null }, "rangeSelector": { "enabled": true, "inputEnabled": true, "buttons": [ { "type": "mtd", "count": 1, "text": "MTD" }, { "type": "ytd", "text": "YTD" }, { "type": "month", "count": 1, "text": "1m", "preventDefault": true, "performancePeriod": "one_month" }, { "type": "month", "count": 3, "text": "3m", "preventDefault": true, "performancePeriod": "three_months_actual" }, { "type": "month", "count": 6, "text": "6m", "preventDefault": true, "performancePeriod": "six_months_actual" }, { "type": "year", "count": 1, "text": "1y", "preventDefault": true, "performancePeriod": "one_year_actual" }, { "type": "year", "count": 3, "text": "3y", "preventDefault": true, "performancePeriod": "one_year_actual" }, { "type": "all", "text": "All" } ], "selected": 5 }, "credits": { "enabled": false }, "yAxis": { "labels": { "style": { "color": false, "fontSize": false } }, "plotLines": [ { "value": 0, "width": 2, "color": "silver" } ] }, "xAxis": { "type": "datetime", "startOnTick": false, "labels": { "style": { "color": false, "fontSize": false } }, "max": null, "events": {} }, "plotOptions": { "area": { "fillColor": { "linearGradient": [ 0, 0, 0, 300 ], "stops": [ [ 0, "#333" ], [ 1, "#444" ] ] } }, "series": { "marker": { "lineColor": "white", "fillColor": "#203A4C", "symbol": "diamond", "radius": 3, "states": { "hover": { "fillColor": "white", "radius": 5 } } }, "compare": "percent", "compareBase": 0 } }, "tooltip": { "crosshairs": true, "dateTimeLabelFormats": { "millisecond": "%b %e, %Y", "second": "%b %e, %Y", "minute": "%b %e, %Y", "hour": "%b %e, %Y", "day": "%b %e, %Y", "week": "%b %e, %Y", "month": "%b %e, %Y", "year": "%b %e, %Y" }, "headerFormat": "<strong>{point.key}<strong><br/>", "split": true, "valueDecimals": 2 }, "series": [ { "id": null, "name": "test", "data": [ [ 1623200400000, 1.3675397235722446 ], [ 1623286800000, 1.3482760115327748 ], [ 1623373200000, 1.3546129384275694 ], [ 1623632400000, 1.3414434698775963 ], [ 1623718800000, 1.3312870572603575 ], [ 1623200400000, 1.3675397235722446 ], [ 1623286800000, 1.3482760115327748 ], [ 1623373200000, 1.3546129384275694 ], [ 1623632400000, 1.3414434698775963 ], [ 1623718800000, 1.3312870572603575 ] ], "lineWidth": 2, "tooltip": { "valueDecimals": 4 } } ] } If I remove the plotOptions.area property nothing changes in the graph, what am I missing?
Notice that with your current data the error occurs in the console: https://assets.highcharts.com/errors/15/ The fillColor feature works only for particular series - like area, pie, funnel, pyramid, arearange etc, so you need to define the type of the series that you want to implemnent. Simplified demo: https://jsfiddle.net/BlackLabel/5r8gxh2b/
Declaring minimal width of serie in treemap
I have treemap chart and it has two values Squadra2 with value of 13778.00 and Squadra1 with value of 16.00 Now when treemap renders it takes percentage difference between them and split them accordingly BUT now I ended up in situation where I need to be sniper precise in order to select Squadra1 with value of 16.00 As you can see in the picture Is there a possibility to declare for example minimal width of Squadra1, and to disallow it to go under that value ( to remain clickable ) ? Please let me know, thank you { "chart": { renderTo:"container", "backgroundColor": "#FFFFFF" }, "colorAxis": { "labels": { "enabled": false }, "tickLength": 0, "gridLineWidth": 0, "min": 0, "max": 20, "stops": [ [ -0.001, "#ffffff" ], [ 0.5, "#7cb5ec" ], [ 0.501, "#7cb5ec" ], [ 0.499, "#ffffff" ], [ 1, "#434348" ], [ 1.001, "#434348" ] ] }, "legend": { "enabled": true, "itemStyle": { "color": "#FFF" } }, "tooltip": {}, "series": [ { "drillUpButton": { "position": { "align": "center", "verticalAlign": "bottom" }, "theme": { "fill": "white", "stroke-width": 1, "stroke": "silver", "r": 2, "style": { "fontSize": "12px" }, "states": { "hover": {} } } }, "type": "treemap", "layoutAlgorithm": "squarified", "allowDrillToNode": true, "dataLabels": { "enabled": false }, "levelIsConstant": false, "levels": [ { "level": 1, "dataLabels": { "enabled": true }, "borderWidth": 6, "borderColor": "#FFFFFF" } ], "data": [ { "id": "id_0", "name": "Squadra1", "parentName": "Squadra1" }, { "id": "id_0_0", "name": "ACC", "parent": "id_0", "parentName": "Squadra1", "scale": 0, "value": 1, "colorValue": 1.8117836848479765 }, { "id": "id_0_1", "name": "FEB", "parent": "id_0", "parentName": "Squadra1", "scale": 0, "value": 0, "colorValue": 5.48633338681632 }, { "id": "id_0_2", "name": "MAG", "parent": "id_0", "parentName": "Squadra1", "scale": 0, "value": 8, "colorValue": 3.4398769612396007 }, { "id": "id_0_3", "name": "PAM", "parent": "id_0", "parentName": "Squadra1", "scale": 0, "value": 7, "colorValue": 2.775814171372472 }, { "id": "id_1", "name": "Squadra2", "parentName": "Squadra2" }, { "id": "id_1_0", "name": "ACC", "parent": "id_1", "parentName": "Squadra2", "scale": 10, "value": 13778, "colorValue": 13.595706940649173 } ], "events": {}, "_colorIndex": 0 } ], "subtitle": { "text": "", "align": "", "style": { "color": "", "fontSize": "", "fontFamily": "", "fontStyle": "none", "textDecoration": "none", "fontWeight": "none" } }, "title": { "text": "", "align": "", "style": { "color": "", "fontWeight": "none", "fontSize": "", "fontFamily": "", "fontStyle": "none", "textDecoration": "none" } }, "lang": { "noData": "" }, "noData": { "style": { "color": "", "fontSize": "", "fontFamily": "", "fontStyle": "none", "textDecoration": "none", "fontWeight": "none" }, "position": { "align": "", "verticalAlign": "middle" } }, "credits": { "enabled": false }, "plotOptions": { "series": { "turboThreshold": 5000, "colorByPoint": false } } } Link of fiddle http://jsfiddle.net/3k5fmrut/2/
The easiest way to achieve it is to set a smaller value for Squadra2 and add an additional property with real value to point object that can be used in tooltip.formatter callback to present the real value in the tooltip. Check demo and code posted below. Code: data: { "id": "id_1", "name": "Squadra2", "realValue": 13778, "parentName": "Squadra2" }, { "id": "id_1_0", "name": "ACC", "parent": "id_1", "parentName": "Squadra2", "scale": 10, "value": 137.78, "colorValue": 13.595706940649173 } tooltip.formatter: tooltip: { formatter: function() { return this.point.realValue; } } Demo: https://jsfiddle.net/BlackLabel/trz96fy7/
You can define your own algorithm to build the treemap : Highcharts treemap series You could choose an algorithm such that each element has a minimum width and height, and the biggest elements share the remaining space.
Chart.js bar graph not centered when there is only 1 item
When there is only one item in a bar graph the bar isn't centered: https://codepen.io/anon/pen/rKmrpX?editors=1010 HTML: <canvas id="myChart" width="400" height="400"></canvas> JS: var ctx = document.getElementById("myChart"); var myChart = new Chart(ctx, { type: 'bar', data: { "labels": ["2018-06-01T04:00:00.000Z"], "datasets": [{ "type": "bar", "label": "Earnings", "yAxisID": "left-y-axis", "borderColor": "rgba(107, 165, 57, 1)", "backgroundColor": "rgba(107, 165, 57, 0.4)", "data": [25.77] }, { "type": "line", "label": "Pageviews", "yAxisID": "right-y-axis", "backgroundColor": "rgba(70, 152, 203, 0.4)", "borderColor": "rgba(70, 152, 203, 1)", "pointBackgroundColor": "rgba(70, 152, 203, 1)", "pointRadius": 0, "data": [3426] }] }, options: { "scales": { "xAxes": [{ "maxBarThickness": 100, "type": "time", "offset": true, "time": { "unit": "day", "tooltipFormat": "MMM-D", "displayFormats": { "day": "MMM-D", "month": "MMM" } }, "ticks": { "maxRotation": 0, "maxTicksLimit": 7, "autoSkip": true }, "gridLines": { "display": false, "offsetGridLines": true } }], "yAxes": [{ "id": "left-y-axis", "type": "linear", "position": "left", "ticks": { "beginAtZero": true }, "scaleLabel": { "display": true, "labelString": "Earnings" } }, { "id": "right-y-axis", "type": "linear", "position": "right", "ticks": { "beginAtZero": true }, "gridLines": false, "scaleLabel": { "display": true, "labelString": "Pageviews" } }] }, "tooltips": { "callbacks": {} } } }); Is there a fix for this? Perhaps I'm missing an option that should be passed in? Using the latest version of Chart.js (2.7.2) here.
Removing most of the xAxes config seams to give the result you are looking for https://codepen.io/tryggvigy/pen/rKmQpX?editors=1010 "scales": { "xAxes": [{ "maxBarThickness": 100, }],
legend overlaps the chart in highchart after restore down the browser
I'm working on a chart given below. https://jsfiddle.net/2nn9q1oo/6/ (see code at bottom of question) The margin is set for legend but it is not working when I click on Restore down on browser. The issue being that the legend overlaps the chart. $('#container').highcharts({ "chart": { "zoomType": "x", "spacingRight": "5", "spacingBottom": 0, "marginBottom": "50", "backgroundColor": "#FFFFFF", "renderTo": "container_0-0_CA3B1DE2-93BC-E451-B40E-EA0594CF6192" }, "defs": { "patterns": [{ "id": "0099CCpattern", "path": { "d": "M 0 0", "stroke": "#0099CC", "strokeWidth": 1 } }] }, "title": { "text": null }, "subtitle": { "text": null }, "credits": { "enabled": false }, "xAxis": { "title": { "text": "", "style": { "color": "#333", "fontWeight": "normal", "fontSize": "12px", "fontFamily": "Trebuchet MS, Verdana, sans-serif" } }, "lineColor": "#909090", "categories": ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", "Y"], "lineWidth": 1.3, "labels": { "staggerLines": 1, "enabled": true, "align": "center", "rotation": 0 } }, "yAxis": [{ "className": "highcharts-axisv1", "plotLines": [{ "value": 0, "color": "#909090", "width": 1 }], "gridLineWidth": 0, "minorGridLineWidth": 0, "gridLineColor": "#EEEEEE", "lineColor": "#909090", "lineWidth": "0", "reversedStacks": false, "max": null, "title": { "text": "ACT (Mio. EUR)Mio. EUR", "style": { "color": "#333", "fontWeight": "normal", "fontSize": "12px", "fontFamily": "Trebuchet MS, Verdana, sans-serif" } }, "labels": { "enabled": false } }, { "className": "highcharts-axisv2", "plotLines": [{ "value": 0, "color": "#909090", "width": 1 }], "gridLineWidth": 0, "minorGridLineWidth": 0, "gridLineColor": "#EEEEEE", "lineColor": "#909090", "lineWidth": "0", "reversedStacks": false, "title": { "text": "", "style": { "color": "#333", "fontWeight": "normal", "fontSize": "12px", "fontFamily": "Trebuchet MS, Verdana, sans-serif" } }, "opposite": true, "labels": { "enabled": false } }], "legend": { "highlightSeries": { "enabled": true }, "enabled": true, "layout": "horizontal", "align": "center", "verticalAlign": "bottom", "floating": false, "padding": 0, "margin": 120, "itemStyle": { "fontWeight": "normal" } }, "plotOptions": { "column": { "stacking": null, "grouping": true }, "series": { "events": {}, "point": { "events": {} }, "dataLabels": { "style": { "fontSize": "9px" } } } }, "tooltip": {}, "series": [{ "type": "column", "name": "PYssss", "data": [598139000, 539771000, 625096000, 663746000, 591762000, 703818000, 781812000, 605727000, 617162000, 713368000, 669983000, 640068000], "stack": "0", "yAxis": 0, "color": "#66CCFF", "borderWidth": 0, "visible": true, "pointPadding": -0.3, "groupPadding": 0.25, "appendix": "Mio. EUR", "decimal": "1", "displayOrder": "0", "index": "0", "legendIndex": "0", "zIndex": "10" }, { "type": "column", "name": "CYwwwww vwwwww ww", "data": [596511000, 655649000, 786752000, 609689000, 853660000, 794944000, 749294000, 673385000, 793836000, 0, null, null], "stack": "0", "yAxis": 0, "color": "#0099CC", "borderWidth": 0, "visible": true, "pointPadding": -0.3, "groupPadding": 0.25, "dataLabels": { "enabled": true, "color": "black", "inside": false, "crop": false, "overflow": "none", "style": { "fontWeight": "normal" } }, "appendix": "Mio. EUR", "decimal": "1", "displayOrder": "1", "index": "1", "legendIndex": "1", "zIndex": "10" }, { "type": "column", "name": "BUDwwwwwwww", "data": [589905625.92, 578155929.93, 665928500.46, 640189735.54, 637354917.64, 672093454.04, 672548027.03, 627794143.76, 693162911.45, 688321249.35, 672359718.53, 692690283.6], "stack": "0", "yAxis": 0, "color": "white", "borderWidth": 1, "visible": true, "form": "budgetCols", "borderColor": "#0099CC", "pointPadding": -0.3, "groupPadding": 0.25, "appendix": "Mio. EUR", "decimal": "1", "displayOrder": "2", "index": "2", "legendIndex": "2", "zIndex": "10" }] }); How can I avoid this?
Staged labels for xaxis with zero values
I'm trying to draw a combination chart with two series represented with bars. Each one has its own xaxis, on the top and in the bottom. In my example I have one of them with zero values. The problem is that xaxis for the series with zero values is staged (bottom xaxis in the example). I don't know why. If I modify the series to non-zero values the xaxis labels are perfect. $(function () { $('#container').highcharts({ "colors": ["#00bdbd","#666666"], "legend": { "align": "center", "verticalAlign": "top", "x": 0, "y": 10, "borderWidth": 0 }, "xAxis": { "labels": { "rotation": 0, "align": "right", "staggerLines": 1, "y": 4 }, "title": { "style": { "color": "#757477" } }, "categories": ["Asturias","Cantabria"], "lineWidth": 0, "tickLength": 0 }, "yAxis": [{ "title": { "text": "Tourists", "style": { "color": "#666666" } }, "min": 0 }, { "title": { "text": "Tourists", "style": { "color": "#666666" } }, "min": 0, "opposite": true }], "series": [{ "name": "Zero", "type": "bar", "data": [0,0], "yAxis": 0, "stack": 0, "zIndex": 0, "animation": true }, { "name": "Visits", "type": "bar", "data": [8000,3000], "yAxis": 1, "stack": 1, "zIndex": 0, "animation": true }] }); }); In this highcharts example you can see the problem. Thank you.
You can set staggerLines parameter as 1. labels:{ staggerLines:1 }, Example: http://jsfiddle.net/2wusojab/1/