JSFiddle - React, Tailwind, and code Playground
by longmatthewh
HTML
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
CSS
#container {
min-width: 300px;
max-width: 800px;
height: 300px;
margin: 1em auto;
}
JavaScript
/*
PROBLEM:
When there are borders applied to series columns, and the series point value is small,
they are cutoff by the border and can be both difficult to read and aesthetically unappealing. Certain column charts could take advantage of offsetting the point value when it cannot fit within the plotted series.
*/
/*
SCENARIO 1
This is the default behavior. Notice how the point y value is cutoff a bit when the value is 1.
*/
const scenario1 = false;
/*
SCENARIO 2
This offsets the series point y value when it cannot fit within the plotted area.
*/
const scenario2 = true;
/*
The following line lets you easily use the varios scenarios above.
*/
const useValueOffset = scenario2;
const [clip, gridLineColor, xAxisOffset] = [false, "transparent", 2];
const seriesConfig = {
type: "column",
clip: clip,
}
const seriesData = [{
...seriesConfig,
data: [1, 4, 3, 5],
}, {
...seriesConfig,
data: [2, 1, 5, 4],
}, {
...seriesConfig,
data: [3, 2, 1, 2],
}];
const categories = ['Apples', 'Pears', 'Bananas', 'Oranges'];
const offsetPointValue = (pointLabel) => {
const value = pointLabel.y;
const minSeriesHeightWhereLabelFitsInside = 12;
const shape = pointLabel.point.shapeArgs;
if (shape.height > minSeriesHeightWhereLabelFitsInside) {
return `<div>${value}</div>`;
}
const labelRightOffset = -1 * (Math.floor(shape.width / 2) + 1);
const labelTopOffset = -7;
return `<div style='position:absolute;width:100%;right:${labelRightOffset}px;top:${labelTopOffset}px;'>-${value}</div>`;
}
Highcharts.chart('container', {
chart: {
spacingRight: 20,
},
xAxis: {
categories: categories,
offset: xAxisOffset,
},
yAxis: {
gridLineColor: gridLineColor,
stackLabels: {
enabled: false,
},
},
plotOptions: {
column: {
stacking: "normal",
borderColor: "#000",
borderWidth: 3,
dataLabels: {
enabled: true,
useHTML: true,
crop: false,
allowOverlap: false,
...