Displaying Points And Drilldown Data in Highmaps - highcharts

I'm having a problem using Highmaps to display both heat map data as well as points on a map. Here is a example:
http://jsfiddle.net/3se9q3uq/
This is the just out of the box example for a US drill down map ( http://www.highcharts.com/maps/demo/map-drilldown ) but I've modified it so that if you drill down into the state of Illinois I'm attempting to add a single point (within a series) to the map.
Below is the snippet I'm using to do this:
chart.addSeries({
id: 'points',
type: 'mappoint',
name: 'Store Data',
color: Highcharts.getOptions().colors[8],
data: [{
name: 'Point 1',
lat: 40.0633,
lon: -88.2498
}]
});
The result (if you open your browsers console) is an error stating:
Highcharts error #22: www.highcharts.com/errors/22
I've tried converting coordinate systems and instead plot X & Y:
var pos = chart.fromLatLonToPoint({
lat: json[i].latitude,
lon: json[i].longitude
});
But that didn't work as it fails to convert the points, returning 0 for X and null for Y. I've also tried changing the map type but that doesn't work either.
I can create a map of just points without drill down but I cannot seem to get layers of heat map like effect (colors) with drill downs that have the same effect and points. I don't see a limitation listed anywhere on their side about points and drill down / coloring segments.
Has anyone been able to get this working before? Am I thinking of these map layers to generically and this just isn't doable?

To use latitude and longitude you need to include Proj4js. Also, you need to either do manual conversion between coordinate systems, or be using maps from the Highmaps map collection. For example:
<script src="http://.../proj4.js"></script>
<script src="http://code.highcharts.com/mapdata/countries/us/us-all.js"></script>
In your case the drilldown example wraps the Highchart.maps in Highcharts.geojson to include extra attributes (drilldown and value), like this:
var data = Highcharts.geojson(Highcharts.maps['countries/us/us-all']);
$.each(data, function (i) {
this.drilldown = this.properties['hc-key'];
this.value = i; // Non-random bogus data
});
$('#container').highcharts('Map', {
// ...
series : [{
data : data,
name: 'USA'
}]
});
This seems to cause Highmaps to not recognize the map as one from the collection, and you are therefor not allowed to use latitude and longitude with this method.
Instead, you can use Highcharts.maps as it is, and use both mapData and data with joinBy to attach extra data that way, while keeping the latitude/longitude functionality, like this:
var myData = [{
"hc-key": "us-ma",
"value": 1
}];
$('#container').highcharts('Map', {
// ...
series : [{
data : myData,
mapData : Highcharts.maps['countries/us/us-all'],
joinBy: 'hc-key',
name: 'USA'
}]
});
Unfortunately, in using this technique on two levels (top and drilldown) and your additional point-series I encountered all kinds of problems. Strangely including the same information in both data and mapData seem to avoid them, so I ended up with this approach:
var mapData = Highcharts.maps['countries/us/us-all'],
myData = Highcharts.geojson(Highcharts.maps['countries/us/us-all']);
$.each(myData, function (i) {
this['hc-key'] = this.properties['hc-key'];
this.drilldown = this.properties['hc-key'];
this.value = i;
});
$('#container').highcharts('Map', {
// ...
series : [{
data : myData,
mapData : mapData,
joinBy: 'hc-key',
name: 'USA'
}]
});
See this updated JSFiddle of how it currently looks with drilldown, latitude/longitude support and point series.
I'll also include this JSFiddle, which uses the more standard data approach (instead of cloning mapData), but has all kinds of problems which I'm not quite sure why they happen.

Related

How to refactor this code so only some properties are shared between variables in Swift

I only just began learning swift and wanted to create a simple chart displaying some data.
I am creating a line chart using AnyChart library and there is a series of lines I am plotting to the chart. I noticed that I am repeating pretty much all of the properties. How can I make the below code less dry.
I am creating a line chart using AnyChart library and there is a series of lines I am plotting to the chart. I noticed that I am repeating pretty much all of the properties, the only thing that is changing is the initial variable name.
How can I make produce less code that will take into account the names of the variables intact (series 1, series 2)?
let series1Mapping = set.mapAs(mapping: "{x: 'x', value: 'value'}")
let series2Mapping = set.mapAs(mapping: "{x: 'x', value: 'value2'}")
let series1 = chart.line(data: series1Mapping)
let series2 = chart.line(data: series2Mapping)
series1.name(name: data.seriesNames[0])
series1.hovered().markers().enabled(enabled: true)
series1.hovered().markers()
.type(type: anychart.enums.MarkerType.CIRCLE)
.size(size: 4)
series1.tooltip()
.position(position: data.position)
.anchor(anchor: anychart.enums.Anchor.LEFT_CENTER)
.offsetX(offset: 5)
.offsetY(offset: 5)
series2.name(name: data.seriesNames[1])
series2.hovered().markers().enabled(enabled: true)
series2.hovered().markers()
.type(type: anychart.enums.MarkerType.CIRCLE)
.size(size: 4)
series2.tooltip()
.position(position: data.position)
.anchor(anchor: anychart.enums.Anchor.LEFT_CENTER)
.offsetX(offset: 5)
.offsetY(offset: 5)
You can do it like this.. Its just a rough idea ...i don't know what is Series object and mapping that you are doing ... But you can have one function that return series and get parameters to create that series
func getSeries(number:Int, mapping:String) -> Series {
let series = chart.line(data: set.mapAs(mapping: mapping))
series.name(name: data.seriesNames[number])
series.hovered().markers().enabled(enabled: true)
series.hovered().markers()
.type(type: anychart.enums.MarkerType.CIRCLE)
.size(size: 4)
series.tooltip()
.position(position: data.position)
.anchor(anchor: anychart.enums.Anchor.LEFT_CENTER)
.offsetX(offset: 5)
.offsetY(offset: 5)
return series
}
And then Create Series
let series1 = getSeries(number:0 , mapping:"{x: 'x', value: 'value'}")
let series2 = getSeries(number:1 , mapping:"{x: 'x', value: 'value2'}")
if you want to make it more simpler ... you can create mapping string from the number as well
Thanks

How do I increase the number of points in a live updating spline chart?

I have a chart like this, you can see that only about 22 points in the chart from left to right. I want to increase this, so that there are more points. Right now it seems very jumpy, but the range is only between 10-11.5, I want to "zoom out" so the line almost looks flat, and these huge peaks and valleys look like little bumps. I've combed over the highcharts documentation and cannot find this config setting.
In the initial creation of the spline chart, an array of point is created, in the default case it is 49 samples, here I changed it to 200, which did what I needed.
series: [{
name: 'Random data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -200; i <= 0; i += 1) {
data.push({
x: time + i * 1000,
y: Math.random()
});
}
return data;
}())
}]

OL3: Clustering Vector Features when can't determine Feature type

I have to load some Features in a Vector layer and have a style function.
var features = new ol.format.GeoJSON().readFeatures( geojsonStr, {
featureProjection: 'EPSG:3857'
});
var vectorSource = new ol.source.Vector({
features: features,
});
/*
var clusterSource = new ol.source.Cluster({
distance: 15,
source: vectorSource
});
*/
var customStyleFunction = function( feature, resolution ) {
....
}
var vectorLayer = new ol.layer.Vector({
//source: clusterSource,
source: vectorSource,
style : customStyleFunction
});
map.addLayer( vectorLayer );
I don't know what kind of geometry I will get in geojsonStr. The problem is: When my collection is of type "Point" I can cluster it, but with any other types I can't see the Layer... How can I cluster Points and ignore Polygons and Lines? or let OL3 be clever enough to decide?
EDIT: I've read https://github.com/openlayers/openlayers/pull/4917
I would recommend you to create 2 different layers: One for clustering and a another one for a common vector layer.
To solve your problem, you can loop through the features and check the geometry type of each, and add it to an already existing source with the addFeature method:
for (var i = 0; i < geojsonFeatures.length; i++) {
if (geojsonFeatures[i].getGeometry().getType() === 'Point') {
clusterSource.addFeature(geojsonFeatures[i]);
} else {
vectorSource.addFeature(geojsonFeatures[i]);
}
}
I have created a jsfiddle which gets a couple of features from a GeoJSON object and add them to different sources depending on the geometry type. If you want to see more points in the cluster souce to make sure that it is working properly, you can use the commented lines as well.

Stock High Charts with Custom points on X-axis

I have a requirement where i have to show custom points on x-axis instead of dates values. Also same custom data points needs to be shown on navigator as well. In the below Js fiddle, i am converting data (Per13/2016 etc) into equivalent date values and then binding the chart using converted date values.
Below is the link of the JS fiddle:- Fiddle link
In the Js fiddle, i am showing Per1,Per2 etc.on x-axis and same has to be shown on navigator as well.
Now i am facing problem with the navigator,when i changes the range using slider ,the x-axis labels changes but not according to the range selected.Also tool-tip formatting is getting changed.
Can you please let me know how to handle this scenario and best way to do the same.
//few code lines to post fiddle link
xAxis: {
labels: {
formatter: function () {
if(fiscal13){
var perDate = new Date(this.value);
return 'Per' + (perDate.getMonth() + 1);
}
}
}
}
I am not sure if I am right, but I think you are overdoing this.
Let's keep original data, so remove fiscal13Data.Data.forEach(function(item) { .. }); function. And When creating data, use simply index of the point as x-value:
var cost = [],
usage = [],
dataLength = fiscal13Data.Data.length
i = 0;
for (i; i < dataLength; i += 1) {
// need to sum costs
cost.push([
i, // the index
fiscal13Data.Data[i]['Cost'] // cost
]);
usage.push([
i, // the index
fiscal13Data.Data[i]['Usage'] // Usage
]);
}
Now you can get to the "Per13/2016" strings in a simple way in xAxis labels' formatters:
var str = fiscal13Data.Data[this.value].Date;
In tooltip formatter, it is almost exactly the same:
var str = fiscal13Data.Data[this.x].Date;
And here is working demo: http://jsfiddle.net/qneuh4Ld/3/
Note: You data looks a bit strange - don't you want to sort it first? Also, you have twice every date (e.g. "Per13/2016" - once for "water" and once for "electric").

Highstock get detailed info when data is grouped

In the click event "this.x" is the first point in the data group.
dataGrouping occurs when you play with the scroll, for example if select show all data, each point represent a week but you have information about every day, so in this point is represented info of all week instead of each day.
¿how I can get the last point in the data group clicked? ¿Hoy can I get the last point represented in this group (in this week)? (week is an example when you play with the scroll grouped data can happen in non common intervals)
plotOptions : {
series : {
point : {
events : {
click : function(event) {
alert(this.x + ' ' + this.y);
//HERE?
}
}
}
}
},
http://jsfiddle.net/JorgeDuenasLerin/QA2Qa/13/
After deep testing and several implementations and reimplementations... the conclusion.
You can access to the points variable. It is the solution because it always has the points draw in the screen and you can access it with no change when dataGrouping occurs.
var point = event.point;
var points = event.point.series.points;
var index = points.indexOf(point);
var index_next = index+1;
Here a working example:
http://jsfiddle.net/JorgeDuenasLerin/QA2Qa/88/
You can not work with series.data variable because it change depending on cropThreshold and number of data.
series.data
here doc:
http://api.highcharts.com/highstock#Series::data
There is no simple way to get it, but here is what you can do:
you have this.x value, now loop through this.series.options.data and compare x-value with your this.x
last object from that comparison (this.x > this.series.options.data[index][0])will be point you are looking for
You can access the series data in the click event by using this.series
events: {
click: function (event) {
var last = this.series.data[this.series.data.length - 1];
alert(last.x + ' ' + last.y);
}
}
http://jsfiddle.net/38FmW/

Resources