quickchart icon indicating copy to clipboard operation
quickchart copied to clipboard

backgroundColor as Array not working

Open mrjemson opened this issue 3 years ago • 2 comments

I have identified an issue with backgroundColor in datasets not working correctly the value is in an array.

If below example is posted to quickchart.io, it renders correctly with colors on all bars, likewise if run in a local browser against charts.js (3.9.1) it renders correctly, however running it against local docker image of latest build, the bars for first person are colored correctly, but bars for all other users are grey.

If backgroundColor is changed to a string value, it works ok, but as an array works across other platforms I feel the same behaviour should be expected.

{ "backgroundColor": "white", "width": 1000, "height": 500, "format": "png", "chart": { "type": "horizontalBar", "data": { "labels": ["Howard", "James", "Fred", "Kylie", "Mark", "Craig"], "datasets": [{ "data": [1, 3, 0, 8, 7, 0], "backgroundColor": ["#388BF7"], "borderWidth": 1, "maxBarThickness": 100, "label": "Votes For" }, { "data": [2, 2, 0, 6, 7, 0], "backgroundColor": ["#2AC0D2"], "borderWidth": 1, "maxBarThickness": 100, "label": "Votes Against" }] }, "options": { "indexAxis": "y", "elements": { "bar": { "borderWidth": 2 } }, "responsive": true, "maintainAspectRatio": false, "legend": { "position": "bottom", "labels": { "color": "#919191" }, "display": true }, "title": { "display": false }, "scales": { "y": { "axis": "y", "ticks": { "color": "#919191", "autoSkip": false, "minRotation": 0, "maxRotation": 50, "mirror": false, "textStrokeWidth": 0, "textStrokeColor": "", "padding": 3, "display": true, "autoSkipPadding": 3, "labelOffset": 0, "minor": {}, "major": {}, "align": "center", "crossAlign": "near", "showLabelBackdrop": false, "backdropColor": "rgba(255, 255, 255, 0.75)", "backdropPadding": 2 }, "grid": { "color": "rgba(145,145,145,0.2)", "offset": true, "display": true, "lineWidth": 1, "drawBorder": true, "drawOnChartArea": true, "drawTicks": true, "tickLength": 8, "borderDash": [], "borderDashOffset": 0, "borderWidth": 1, "borderColor": "rgba(0,0,0,0.1)" }, "type": "category", "offset": true, "display": true, "reverse": false, "beginAtZero": false, "bounds": "ticks", "grace": 0, "title": { "display": false, "text": "", "padding": { "top": 4, "bottom": 4 }, "color": "#666" }, "id": "y", "position": "left" }, "x": { "axis": "x", "ticks": { "color": "#919191", "autoSkip": false, "minRotation": 0, "maxRotation": 50, "mirror": false, "textStrokeWidth": 0, "textStrokeColor": "", "padding": 3, "display": true, "autoSkipPadding": 3, "labelOffset": 0, "minor": {}, "major": {}, "align": "center", "crossAlign": "near", "showLabelBackdrop": false, "backdropColor": "rgba(255, 255, 255, 0.75)", "backdropPadding": 2 }, "grid": { "color": "rgba(145,145,145,0.2)", "borderColor": "rgba(145,145,145,0.2)", "display": true, "lineWidth": 1, "drawBorder": true, "drawOnChartArea": true, "drawTicks": true, "tickLength": 8, "offset": false, "borderDash": [], "borderDashOffset": 0, "borderWidth": 1 }, "type": "linear", "beginAtZero": true, "display": true, "offset": false, "reverse": false, "bounds": "ticks", "grace": 0, "title": { "display": false, "text": "", "padding": { "top": 4, "bottom": 4 }, "color": "#666" }, "id": "x", "position": "bottom" } } } } }

mrjemson avatar Sep 09 '22 03:09 mrjemson

This is an issue introduced by node-canvas 2.7.0. Specifically, array values for fillStyle stopped being supported because it is non-standard according to the canvas spec:

https://github.com/Automattic/node-canvas/commit/4ce04af854da7b63b0ad84a0abd030f95846e55d https://github.com/Automattic/node-canvas/commit/bf5126b3847a02a9ea80febba22aefba88c97ee2

Unfortunately for us, Chrome (v8) and other engines implement this non-standard behavior, leading to the inconsistency you have observed (quickchart.io is running an older version of node-canvas).

I'm not sure what the best fix is for this yet. AFAICT, it'd require a fork or upstream contribution to Chart.js or node-canvas.

typpo avatar Sep 12 '22 00:09 typpo

Finally circling back to this. The issue seems to be more if there are multiple data values and only one one backgroundColor element in the array. If I repeat the same color in the array for as many elements as there are in the data array it works fine.

If i include one in the array it will only color the first data point. If I make it a string, all data elements are colored correctly. As a workaround flattening and single element array to a string seems to work.

mrjemson avatar Oct 14 '22 06:10 mrjemson