Datalabels on Highmaps appearing bottom to top - svg

I am facing a strange problem with Highmaps. I have a geojson map that Highmaps shows properly. Mouseover works and tooltips appear in the correct places. However, when I turn on data labels, they appear upside down. That is, a label that should appear near the bottom of the map (centered on its province) now appears near the top, and vice-versa. The data labels' coordinate system seems to be reversed.
In the image, the label "603863" should appear over the bottom-most province, while "1966085" should appear over the topmost province.
A sample of my geojson data:
var provincePolygons = {
"type":"FeatureCollection",
"features":[
{"type":"Feature",
"properties":{
"id":"05","name":"Tete"},
"geometry":{"type":"Polygon",
"coordinates":[[
[32.636,-14.204],
[33.245,-13.998],
[33.299,-14.032],
[33.300,-14.146],
[33.385,-14.237],
[33.478,-14.404],
[33.544,-14.434],
[33.627,-14.528],
[33.640,-14.594],
[33.718,-14.572],
...
Things I have tried:
The data labels are SVG elements. I thought that maybe surrounding CSS rules might be affecting their position, but since the other CSS elements, using similar transformations, are in the correct locations, that doesn't seem to be the problem.
The longitudes are negative values. I experimented with making them positive by adding +100 to each value, just to see if the negative values were to blame, but they were not. It was a long shot.
I've played, naturally, with the API settings for data labels, but there does not seem to be a switch that affects their top-to-bottom placement. I would also think that leaving the default values untouched should result in correct placement.
I have wondered how data labels' location is calculated by Highmaps. Perhaps Highmaps cannot find the center of each polygon and needs a hint? I added latitude and longitude values to the feature in the geojson, but that did not help. I've also used Highmaps before in a similar situation without needing to add such data.
There is a group called "highcharts-data-labels" in the generated SVG. I am considering trying the flip its coordinate system upside-down somehow to move the data labels to their correct position, but that would a complex intervention for something that should work correctly.
Please note that I am using ng-highcharts.
What am I doing wrong?

For anyone else running into this problem, I was able to solve this by adding the property 'chartType' to my config object. The docs for the highcharts-ng library mention this for making a highstock chart, but don't say anything about it for highmaps. The lib defaults to 'chart', but you need to put chartType: 'map', and it should fix the problem :)
Here's the relevant code from the highcharts-ng libary, where config is your chart Object:
var chartTypeMap = {
'stock': 'StockChart',
'map': 'Map',
'chart': 'Chart'
};
function getChartType(config) {
if (config === undefined || config.chartType === undefined) return 'Chart';
return chartTypeMap[('' + config.chartType).toLowerCase()];
}
Hope this helps!

Related

fabricjs: Issue with multiple paths of SVG having the exact same gradient

For my web app, I am creating SVG elements in Illustrator and then using them in a library of elements that users can add to the fabric canvas.
Some elements are simple but some complex with multiple compound paths etc.
I have came across an unusual issue where if I create a path with a gradient fill, and then copy that path, save the SVG and add it onto the canvas, only the first path would have the gradient and the rest would be flat colors.
Here is a screenshot of what I mean...
After experimenting and trying different things, I finally discovered that this is happening because the paths have the exact same gradient properties.
So if the gradient slider (color stops, opacity, location etc.) of two or more paths have the exact same properties in Illustrator, then the issue occurs.
So the workaround is to alter something like the location (for example) to be 99.9% instead of 100% on the copied path, then the issue goes away. However, this will quickly become a tedious and annoying way to fix this. Basically, each path with a gradient, needs to have a unique gradient set up and cannot be identical to another paths gradient properties.
Here are more screenshots to better explain...
After making this change...
The first and second path's gradient's location are different.
The first, third, fourth and fifth paths have exact same gradient.
This is what it looks like when I add it to the canvas now...
Here is the code I am using to add the SVG to the canvas...
fabric.loadSVGFromURL(image, function(objects, options) {
var oImg = fabric.util.groupSVGElements(objects, options);
oImg.perPixelTargetFind = true;
oImg.targetFindTolerance = 4;
canvas.add(oImg);
canvas.renderAll();
});
Can anyone tell me why this is happening and if there is a way to fix this with code rather than Illustrator? I have hundreds of elements to create that will have many paths with the same gradients. I know it will be a real pain to have to worry about paths not having the exact same gradient.
http://jsfiddle.net/oc70xjsq/
Link to the SVG

SwiftCharts cutting off points (clips bounds)

I am tweaking the Areas Example project from SwiftCharts and I am running into the issue where the point indicators are getting cut off like so:
In the github issues a found this and this other issue where the solutions were to set chartSettings.clipInnerFrame = false
However, when I do this the the area color awkward shape also becomes visible like so:
How can I get the whole shape of the points but all the other stuff?
You have to pass to the ChartPointsViewsLayer with the points clipViews: false (see example). ChartSettings.clipInnerFrame has to be true (i.e. the default). This way only the layer with the points is clipped.
Finally, if you want to clip the unclipped points layer (to limit the area outside of the chart where they are displayed), you can do it passing a custom rectangle, like here (this setting is admittedly not very intuitive).

Combining Multiple SVG Transformations

I'm new to Snap.svg and SVG and experimenting with transformations (an illustraiting plunk can be found here). Basically I'm trying to move, scale and rotate a shape according to its configuration. This is what I've found out so far:
rotating around a point is possible with rotate(angle, x, y)
there is no direct transform method to scale around a point but it can be done as described in "SVG Essentials"
However combining these transforms doesn't give me the expected result - my expected calculated center of the shape differs from the rendered one. Can anyone give me some pointers on how to correctly put these transforms together?
Regards,
Andi
To combine transforms, I would use Snaps own transformString format. I would first have a read of my previous answer on SO here, this is slightly different so posting a slightly different example and answer.
Whilst Snap can use SVGs transform strings (rotate() scale() transform()). They don't by default centre around itself for example, whereas Snaps (and Raphaels) do. This makes it a bit easier. For more complex situations, one may need to look into Matrix methods, but I think the following should be ok...
Snaps transformString uses string t (transform), s (scale), r (rotate), and you can add them repeatedly if wanted.
Here is an example of both methods, to highlight the difference.
jsfiddle here
s = Snap(400, 620);
var r1 = s.rect(0, 0, 100, 100).attr({
fill : 'blue',
stroke : 'black',
opacity: 0.5
});
var r2 = r1.clone().attr({ fill: "red" });
r1.transform('t100,100s2,2r45'); //typical Snap way, rotation/scale around centre
r2.transform('translate(100,100) scale(2,2,) rotate(45)'); //SVG way
The getBBox() method should be pretty reliable as far as I know (maybe post up a separate question on SO if you find an example where it is wrong)

D3 Sunburst clip path of text

I am trying to implement a d3 visualization based on the sunburst diagram, and i have found an almost perfect online example of this which i have got working http://tributary.io/inlet/4127332/:
My main issue is that I need to also Clip the text to the segment,I have tried using the svg clip path but my meager d3 skills have let me down. Any help with this is appreciated.
So my first attempt to clip the text did not work and I think this is because the arc's coordinate space does not line up with the text's coordinate space in the way that you want if you are using the arc generator, as you are.
I found that if I apply the clip to the groups you make for each node then it worked like a charm. There was one caveat. When I tried generating my clip path and then applying them the order that the nodes were joined to the elements differed and so the wrong path were clipping the wrong text. I got around this by adding an id to each data element. You can see the final version here
The important parts are adding the clip paths (note the use of the new id field):
svg.append('defs')
.selectAll("clipPath")
.data(partition.nodes)
.enter().append('svg:clipPath')
.attr('id', function(d,i) { return d.id;})
.append('path').attr('d', arc);
Then you simply have to reference them on your node groups (again using the id):
group =
svg.selectAll("g")
.data(partition.nodes)
.enter().append('svg:g')
.attr('clip-path', function(d,i) { return 'url(#' + d.id + ')';});
In the tributary I put the svg data join first so that the "defs" node would appear in the usual place (first after the svg tag), but I do not think this is technically necessary.

Raphael - find bounding box of text BEFORE printing

Afternoon All,
I'm trying to draw a dynamic "ruler" which can be zoomed (along with the rest of the page) and is annotated, using Raphael.
I've found Raphael's pathBBox() and isBBoxIntersect very useful for determining if a graduation should be printed at a certain point or if it would be too close to another and should thus be skipped.
Now I need to annotate some of the graduations and want to follow a similar method - annotate the largest graduations, working down to the smallest level of detail but skipping drawing the text if it would intersect with some already drawn.
Unfortunately my look through the Raphael docs have only shown me the Paper.print() and Paper.text() methods, both of which add to the paper. This means I would have to add, then find the bbox and test, then remove if bad - which is potentially rather slow.
Is there a way to find the dimensions of some text I want to print without printing it, such that I can manually create a bbox object and test it against my stored bboxes?
As always, thanks very much in advance! :-)
Cheers,
-Oli
You can use .getBBox() on text:
var text = paper.text(...);
if (text.getBBox().width > max) ...;
I didn't see this documented officially, but it works, and apparently cross-browser.

Resources