Bug in new highcharts renderer? - highcharts

The following jsfiddle shows an example where I'm placing text on the chart, getting the width/height of that text, then using the width/height to work out where to place the same text again, but this time in the middle of the chart, and with a bounding box around it:
http://jsfiddle.net/drmrbrewer/mfr0rd4b/3/
The above is using highcharts 4.0.4.
some code
Here is the exact same code, but using highcharts 4.1.1:
http://jsfiddle.net/drmrbrewer/mfr0rd4b/4/
The bounding box has been placed around the first-placed text, despite using the x,y,width,height information from the second-placed text to create the bounding box.
Is this a bug in the new version?
Is there a better way to work out place text, with a bounding box, bang in the middle of a chart? Till now, I've been placing (invisible) dummy text, using width/height of that to work out where to place the real text, then adding the bounding box. Which is why I've run into this issue in the new version.

Well I'm still not sure why the example in the OP broke going from 4.0.4 to 4.1.1, but a partial answer to my question, which at least provides a solution that works even in 4.1.1, is given by the following jsfiddle:
http://jsfiddle.net/drmrbrewer/mfr0rd4b/7/
text = chart.renderer.text("My Text").add();
textBBox = text.getBBox();
x = chart.plotLeft + (chart.plotWidth * 0.5) - (textBBox.width * 0.5);
y = chart.plotTop + (chart.plotHeight * 0.5) - (textBBox.height * 0.25);
text.attr({x: x, y: y, zIndex: 10});
rect = chart.renderer.rect(x, y, textBBox.width, textBBox.height, 2)
.attr({
fill: '#FFFFEF',
stroke: 'gray',
'stroke-width': 1,
zIndex: 9
})
.add();
rectBBox = rect.getBBox();
rect.attr({y: y - rectBBox.height*0.5 - textBBox.height*0.25});
A second mystery is why it's textBBox.height * 0.25 and not textBBox.height * 0.5...
EDIT... dang! The new solution breaks when I add a <br> to split the text across lines:
http://jsfiddle.net/drmrbrewer/mfr0rd4b/8/
Any idea how to fix that?

Related

What is the best way to drag a transformer by dragging from empty areas in Konvajs?

I'm currently following this guide to select shapes in the stage and put them inside a Transformer.
If possible, I'd like to drag an entire Transformer with all of its content without touching any of the shapes inside.
For example, I have two lines that are far from each other. Both of them are nodes inside a Transformer and can be dragged as long as I click one of those 2 lines. However, if I tried to drag from any of the empty area inside the Transformer nothing would happen (or the transformer would reset, depending on the code).
I'm thinking of adding a transparent Rect (this Rect will always have the same size as the Transformer) to the Transformer and then add any other shape that I want inside the Transformer. Since both the Rect and the Transformer have the same size, I could easily drag the entire Transformer from any "empty area" where my other shapes are not located.
I'm not sure if this is the correct/efficient way to do it. How should I tackle this issue to obtain the best outcome?
There is an experimental property shouldOverdrawWholeArea for Konva.Transformer. It is not in the docs yet.
If you set it to true the whole transformer area will be available for drag.
But if you have a transformer on top of other shapes, then shapes will be not listening for regular events (such as click, touchstart etc). Because the transformer rectangle will overdraw hit area of attached shapes. Even will start working as soon, as you remove such a transformer from them.
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth - 20,
height: window.innerHeight - 20
});
const layer = new Konva.Layer();
stage.add(layer);
const shape1 = new Konva.Circle({
x: 70,
y: 70,
radius: 50,
fill: 'green'
});
layer.add(shape1);
const shape2 = shape1.clone({
x: 190,
y: 90
})
layer.add(shape2);
const tr = new Konva.Transformer({
nodes: [shape1, shape2],
shouldOverdrawWholeArea: true
});
layer.add(tr);
layer.draw();
<script src="https://unpkg.com/konva#7.0.3/konva.min.js"></script>
<div id="container"></div>

Shared tooltip positioner point.plotY is always 0 in Highcharts Stacked columns

I have this kind of graphics : https://www.highcharts.com/demo/column-stacked-percent
My problem is that, like in the example, the tooltip lies on the top of each bar. Using the positioner property of the tooltip gives me the possibility of placing it somewhere, however the point.plotY property is always 0. I think that this comes from the fact that tooltip is shared.
I need to place the tooltip on bottom when i'm hovering the top series, because I have some information between bars hidden by the tooltip.
How can I get this point.plotY "real" value or overcome the problem ?
When you have a stacked column, you can get the hover points via this.chart.hoverPoints (this is the tooltip) and choose the point from the stacked column.
If want a specific point which is not part of the hovered column - you can access series object and its via this.chart.series[seriesIndex].data[pointIndex].
Positioner for the tooltip which appears in the bottom point:
positioner: function (w, h, p) {
const chart = this.chart
const points = chart.hoverPoints
if (points && points.length) {
const i = points.length - 1
return { x: points[i].plotX + chart.plotLeft - w / 2, y: points[i].plotY + chart.plotTop}
}
return { x: 0, y: -9e7 }
}
example: http://jsfiddle.net/8acems26/

How to align text in center using jspdf

How to align text center using jsPDF.
var doc = new jsPDF();
doc.text(40, 250, 'Hi How are you');
If you are using the latest version (1.1.135) the api has changed some for the text function. It now reads as:
API.text = function(text, x, y, flags, angle, align);
If you don't need to use the flags or angle though, you can simply use:
var doc = new jsPDF();
doc.text('Hi How are you', 40, 250, 'center');
Keep in mind that the center call uses the x parameter now as the center of the text string, and not the left most border as it does when rendering left aligned.
Link to source
Edit:
Alternately you can calculate the proper x offset to just use the text function normally like so:
var text = "Hi How are you",
xOffset = (doc.internal.pageSize.width / 2) - (doc.getStringUnitWidth(text) * doc.internal.getFontSize() / 2);
doc.text(text, xOffset, 250);
Angular 6.
Footer align to horizontally center
var doc = new jsPDF();
var pageHeight = doc.internal.pageSize.height || doc.internal.pageSize.getHeight();
var pageWidth = doc.internal.pageSize.width || doc.internal.pageSize.getWidth();
// FOOTER
let str = "Your footer text";
doc.setTextColor(100);
doc.setFontSize(10);
doc.text(str, pageWidth / 2, pageHeight - 10, {align: 'center'});
doc.save("example.pdf");
Above answers didn't work for me, I ended up doing the following to center the text
let textX = (doc.internal.pageSize.getWidth() - doc.getTextWidth(text))/2
doc.text(text, textX, textY);
this worked:
var xOffset = doc.internal.pageSize.width / 2
doc.text('hello world', xOffset, 8, {align: 'center'});
2022: this works assuming your page width is 210 (default A4).
doc.text("This is centred text.", 105, 80, null, null, "center");
Here's a link to their live demo per the README:
http://raw.githack.com/MrRio/jsPDF/master/index.html
2022: I'm finding that JSPDF is buggy. It took a while to figure out how to install the advertised 'runs in a browser' implementation for a PHP app instead of a JS front end framework. There's a line that's required window.jsPDF = window.jspdf.jsPDF; that isn't mentioned anywhere in the documentation, I had to go through a downloaded example piece by piece to find it. Now I'm finding that the center text function doesn't work. In 2 different local environments and a JSFiddle, on multiple browsers, it sends the text off the left side of the page when the align:center option is implemented. While the above solution works, it breaks down if text is longer than one line, which, incidentally, is another out of the box bug - the text runs out of the document instead of wrapping, and there is no wrap option. So, it seems after all these hours I'm out of luck and I'll have to go a different route. Plugin is not maintained and this should be noted in documentation. Recommend to not waste your time.
This works somewhat, but isn't precise, if you know please tell me why.
I calculate the width of my text in order to center it myself.
For this, I used the getTextDimensions() method on my jsPDF object
var pdf = new jsPDF({
orientation : 'p',
unit: 'px',
format: [500, 750],
putOnlyUsedFonts:true
});
var textDimensions = pdf.getTextDimensions('MyText');
You can now use textDimensions.w to get text-width and textDimensions.h for height
Then use this to center your text.
var textWidth = textDimensions.w;
pdf.text('MyText', (pdfWidth / 2) - (textWidth / 2), 100);
BUT: You need to know your PDF's width to do this.
I 'solved' this by defining height and width myself, but you can easily find height and width of common formats online.
Like A4: 210mm*297mm.
Just remember to set unit: 'mm' when creating your jsPDF.
var doc = new jsPDF();
// set midPage for variable use
var midPage = doc.internal.pageSize.getWidth()/2
// Default is 210 mm so default midway by value is 105
doc.setFontSize(40);
doc.text("Octonyan loves jsPDF", 105, 15, null, null, "center");
// Better to use a variable "midPage" (from above)
doc.setFontSize(30);
doc.text("Centered (USA), Centred (UK)", midPage , 30, null, null, "center");

Wrong rendering of y-axis in polar charts

I need help with the y-axis of polar charts like spiderweb or windrose.
I've an application with an dashboard which contains some widget, each containing an iframe with an Highcharts chart.
Because these widgets are reziable, I've some javascript for resizing the container of the charts.
$(window).bind("resize", resizeChart);
function resizeChart() {
var width = $(document).width() - 55;
var height = $(document).height() - 60;
$("#container").css("width", width);
$("#container").css("height", height);
}
Some example: http://jsfiddle.net/CwnDw/
My problem is, that the scale of the y-axis often look very ugly. When the chart loads the y-axis has only one tick.
After resizing the chart to + 10 px, it contains no tick, and after resizing to the inital size, the y-axis renders with 5 ticks. I don't understand why.
In my example I only get these effect when I resize the chart from a small size to a bigger size very fast.
Is there a better way for resizing a chart? I tried the chart.setSize() function to, but no effect. Or: is there a way to rerender/recalculate the y-axis?
Thank you
Torben
I'm not sure about a redrawing method that would accomplish what you are looking for, but with my experience using Highcharts, I found it is best to specify tick positions to avoid any unexpected results.
Here is a link to Highchart documentation regarding yAxis: tickPosition
http://api.highcharts.com/highcharts#yAxis.tickPositions
There is a pretty good jsFiddle example there that should cover implementation.
Try this:
function resizeChart() {
var width = $(document).width() - 55;
var height = $(document).height() - 60;
$("#container").css("width", width);
$("#container").css("height", height);
setTimeout(function () {
chart1.setSize(
width,
height,
false
);
},10);
}
http://jsfiddle.net/9YFB8/2/

Highcharts bar chart with fixed bar widths and gaps

I've set
pointWidth: 20,
pointPadding: 0,
groupPadding: 0
But the chart still expands to fill the default chart height. Is it possible to have Highcharts adjust the chart height instead?
http://jsfiddle.net/MLELM/
The chart will fill the available height with what you give it.
point and group padding are a proportion of the available space, so the chart is honoring the properties as specified.
It uses the size of the containing element to determine its size, so it cannot possibly ignore the height of the containing element.
If you want a smaller chart that fills a larger space on your page, you can put your containing element in another wrapper element. Then you can calculate yourself how tall your chart should be based on the number of series, and pass that height to the container.
If you want to have the series that you have specified clustered near the top, you will need to add additional null data points to fill the space below them.
If you can be more specific about what you want and why, better answers may be available.
[[ update
Stumbled across this post again, and remembered that I have a demo that automatically sets the chart height based on some predefined parameters, and the number of data points.
var barCount = chartData.length,
pointWidth = 20,
marginTop = 70,
marginRight = 10,
marginBottom = 50,
marginLeft = 100,
groupPadding = 0,
pointPadding = 0.3,
chartHeight = marginTop
+ marginBottom
+ ((pointWidth * barCount)
* (1 + groupPadding + pointPadding));
Fiddle here:
http://jsfiddle.net/jlbriggs/kpu5d1qf/
Related question here:
How to calculate the height of bar chart
Yes, you can set the chart height like that:
chart: {
type: 'bar',
height: 200,
},
See also http://jsfiddle.net/MLELM/3/

Resources