In the past I have drawn tables below the chart based on the series. This works because I can tell Highcharts to vertically align the legend, move it to the left, and I can use the legend height and positioning as well as x-axis tick information to figure out where to draw the table lines:
This takes advantage of the fact that once I set the legend vertical, Highcharts is going to internally set the viewport (viewbox?) large enough that the legend is visible, and since my table aligns with the legend, it's also visible.
Now I have a situation where I need to draw a table below the chart that is not based on the series. I actually moved the legend to be floating in the upper right of the chart because there's only one series and it fits nicely there.
I figured out how to position my table lines based on the x-axis label box dimensions (along with tick information), but my table extends out of the viewport (viewbox?) and is not visible:
If I go after the fact and do
myChart.renderer.box.setAttribute("viewBox", "0 0 1200 1200")
to "zoom out", I can see that my whole table did draw, it's in there in the SVG:
So - how do I tell the Highcharts renderer to extend the viewport/viewbox/canvas (whatever the correct term is) down so that when I add my table, it's visible?
I trigger the table drawing from a redraw
event handler, and if it's a question of setting some option/parameter I can easily do the calculations I need to figure out how much to extend beforehand and include that in a chart.update({...stuff...}, true)
so that it's the right size already when I go to draw my table.
Or I can mess with the chart.renderer
directly in code if that's what it will take.
CodePudding user response:
Ok, figured it out.
chart.renderer
has a function to setSize
, which will set the overall size of the SVG root element itself, however the SVG root is contained within the "highcharts container" div
, which has inline CSS styles to set height and width, and importantly, has overflow: hiddden
, so you have to also set the height of the container div
in order for the increased SVG to be visible. Luckily that is easily accessible at chart.container
.
In my case I need to conditionally draw a table after a zoom in or out, so in my function to actually draw the table I also calculate the height it will need and return that so that I can adjust the SVG root and container div
after the table is drawn. It looks a little like this:
const drawTable = async (chart, dataForTable) => {
// figure out how much room the table is going to take up
const extraHeight = (rowHeight * dataForTable.length) littleExtraOffset
// create the SVG container for the table
const group = chart.renderer.g('bottom-table').add();
// draw all the lines for the table etc and add them to the group, then
return {
group,
extraHeight
}
}
const redrawEventHandler = (event) => {
// do stuff to figure out if we need to draw a table or not
let newWidth = baseWidth;
let newHeight = baseHeight;
if (shouldDrawTable) {
const { dataForTable } = this.props;
drawTable(event.target, dataForTable).then(tableResult => {
// save the table SVG group so we can easily destroy it later
this.tableGroup = tableResult.group;
// calculate the new total height
newHeight = tableResult.extraHeight;
this.chart.renderer.setSize(newWidth, newHeight);
this.chart.container.style.height = `${newHeight}px`;
});
} else {
// no table, newWidth and newHeight are still
// the original height and width
this.chart.renderer.setSize(newWidth, newHeight);
this.chart.container.style.height = `${newHeight}px`;
}
}