HighMap data label is shown rotated - highcharts

I tried to display some map results in JustPy, but HighMap data labels in JustPy show as rotated, but only the label is roated not the map itself.
import justpy as jp
my_chart_def = """
{
chart: {
map: 'custom/europe',
borderWidth: 1
},
title: {
text: 'Nordic countries'
},
subtitle: {
text: 'Demo of drawing all areas in the map, only highlighting partial data'
},
legend: {
enabled: false
},
series: [{
name: 'Country',
data: [
['is', 1],
['no', 1],
['se', 1],
['dk', 1],
['fi', 1]
],
dataLabels: {
enabled: true,
color: '#FFFFFF'
},
}]
}
"""
def chart_test():
wp = jp.WebPage()
wp.head_html = """
<script src="https://code.highcharts.com/maps/9.2.2/highmaps.js"></script>
<script src="https://code.highcharts.com/mapdata/custom/europe.js"></script>
"""
my_chart = jp.HighCharts(a=wp, classes='m-2 p-2 border w-1/2 h-screen', options=my_chart_def)
my_chart.options.chart.type = 'map'
my_chart.options.series[0].name = 'Test chart'
my_chart.options.title.text = 'Data'
return wp
jp.justpy(chart_test)
This is what I got:
If I rotate the map 90 degrees, this is what I see, and the label seems aligned

I've reproduced your example in the editor, and everything seems to be correct https://jsfiddle.net/BlackLabel/6g92m7br/, so the issue occurs from the justpy side.
However, since 9.3.0 Highcharts Maps has improved geometry https://www.highcharts.com/blog/changelog/#highcharts-maps-v9.3.0, which could have affected another framework's behaviour. I would suggest reaching out JustPy developers directly.
As a workaround, you can try to play around with setting x, y dataLabels positions, e.g:
plotOptions: {
series: {
dataLabels: {
x: 15,
y: -50
}
}
}
Demo:
https://jsfiddle.net/BlackLabel/bnejx2kc/
API Reference:
https://api.highcharts.com/highmaps/plotOptions.map.dataLabels.x
https://api.highcharts.com/highmaps/plotOptions.map.dataLabels.y

Related

Highmaps display correctly mappoints but not maplines

I need to use Highmaps to display on a map some information such as points, lines...
Displaying the initial map and some mappoint (with latitude/longitude coordinates) works well.
But when I add a simple mapline (linestring) between 2 points already displayed on the map, the mapline is not drawn.
Here is an example : https://jsfiddle.net/vegaelce/4L928trp/
The 2 mappoints are correctly placed on the map with the following data :
data: [{
name: 'Paris',
geometry: {
type: 'Point',
coordinates: [2.34,48.86]
}
}, {
name: 'Orly',
geometry: {
type: 'Point',
coordinates: [2.40,48.75]
}
}]
But the mapline (named "road") added to link the 2 points is not displayed with the following data :
data: [{
geometry: {
type: 'LineString',
coordinates: [
[2.34,48.86], // Paris
[2.40,48.75] // Orly
]
}
}],
Do I need to add something else ?
If you use the TopoJSON maps, what you are trying to do works. https://jsfiddle.net/blaird/y1Ld6bgs/1/
(async () => {
const topology = await fetch(
'https://code.highcharts.com/mapdata/countries/fr/fr-idf-all.topo.json'
).then(response => response.json());
// Prepare demo data. The data is joined to map using value of 'hc-key'
// property by default. See API docs for 'joinBy' for more info on linking
// data and map.
var data = [
["fr-idf-se", 69699],
["fr-idf-hd", 14200],
["fr-idf-ss", 17301],
["fr-idf-vo", 14350],
["fr-idf-vm", 29728],
["fr-idf-vp", 28610],
["fr-idf-yv", 21667],
["fr-idf-es", 16494]
];
// Create the chart
Highcharts.mapChart('container', {
chart: {
map: topology
},
title: {
text: 'Highcharts Maps basic demo'
},
subtitle: {
text: 'Source map: Île-de-France'
},
series: [{
mapData: Highcharts.maps["countries/fr/fr-idf-all"],
data: data,
name: "States",
borderColor: "#ffffff",
joinBy: ["hc-key", "CODE_REGION"],
keys: ["CODE_REGION", "value"]
}, {
type: 'mapline',
data: [{
geometry: {
type: 'LineString',
coordinates: [
[2.34, 48.86], // Paris
[2.40, 48.75] // Orly
]
}
}],
showInLegend: true,
lineWidth: 2,
name: "Road",
nullColor: '#f00',
color: '#f00',
enableMouseTracking: false
}, {
type: 'mappoint',
color: '#333',
name: "Towns",
showInLegend: true,
data: [{
name: 'Paris',
geometry: {
type: 'Point',
coordinates: [2.34, 48.86]
}
}, {
name: 'Orly',
geometry: {
type: 'Point',
coordinates: [2.40, 48.75]
}
}],
enableMouseTracking: false
}]
});
})();
In the Adding Points and Lines doc: https://www.highcharts.com/docs/maps/adding-points-and-lines
Prior to v10, the coordinate system used in most of our maps was a
custom one, where both the X and Y values ranged from 0 to some
thousands. This still applies when loading GeoJSON maps rather than
TopoJSON maps from the Map Collection. With the support of the proj4js
library, points could be placed by the lon and lat options. Without
proj4.js, points were added as x, y pairs on the same coordinate
system as the map. Maplines however were given as paths.
It explains that if you don't use the Topo data, you'll have to either convert the coordinates, or use the same coordinate system as the map for lines.
P.S. Not sure why setting color of the line doesn't work, but setting nullColor does. But, that is what I had to do to make the line red
After digging into I think that it is a bug and I reported it on the Highcharts Github issue channel where you can follow this thread: https://github.com/highcharts/highcharts/issues/17086

Column chart with categorised Y axis

I'm trying to assign categories to the Y Axis on a column chart. I've tried using categories but this causes a peculiar result with the columns not reaching the X Axis, and the values being incorrect
https://jsfiddle.net/fmgLa5h4/1/
I've tried various other properties to correct this but to no avail.
I've also tried using labels.formatter, which gets a slightly more desirable result but with the labels aligned to the ticks - again I've tried other ways to correct this without success
https://jsfiddle.net/fmgLa5h4/2/
You can try to mapping the data using data.seriesMapping and set your own dataLabels or categories, take a look at this example:
var categories = ['A', 'B', 'C', 'D', 'E'],
yAxisLabels = ['10', '20', '30', '40', '50'];
Highcharts.chart('container', {
data: {
csv: document.getElementById('data').innerHTML,
seriesMapping: [{
// x: 0, // X values are pulled from column 0 by default
// y: 1, // Y values are pulled from column 1 by default
label: 2 // Labels are pulled from column 2 and picked up in the dataLabels.format below
}]
},
chart: {
type: 'column'
},
title: {
text: 'Daily runs'
},
xAxis: {
minTickInterval: 24 * 36e5
},
yAxis: {
labels: {
formatter: function() {
return yAxisLabels[this.value] + ', ' + this.value || '';
},
},
tickInterval: 1,
max: categories.length - 1,
},
legend: {
enabled: false
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
format: '{point.label}'
},
}
}
});
For formatting data tables, yAxis.labels.formatter is a good option. It is possible that your data will need to be formatted before you map it.
Sample concept:
data = data.replace(/\r\n/g, '\n') // Unix
.replace(/\r/g, '\n') // Mac
.split('\n');
data.forEach(function(row, i){
if (i) {
row = row.split(',');
data[i] = row.concat([
categories.indexOf(row[1]),
categories.indexOf(row[3])
]).join(',');
}
});
data = data.join('\n');
Live demo:
https://jsfiddle.net/BlackLabel/g5svkrac/
API References:
https://api.highcharts.com/highcharts/yAxis.labels.formatter
https://api.highcharts.com/highcharts/data.seriesMapping
You meant to positioning the label, you can use yAxis.labels.y to position offset of all labels relative to the tick positions on the axis.
https://jsfiddle.net/BlackLabel/g5svkrac/1/

HighMap data table not loading points

I'm trying to populate a map of the U.S. in HighMaps with data from an html table. The map is showing but the data point is not. It's a latitude/longitude point. The documentation is sparse, so I'm not sure what I'm doing wrong. Here's a JSFiddle: https://jsfiddle.net/sfjeld/1wjm04fc/6/
Highcharts.mapChart('container', {
chart: {
map: 'countries/us/custom/us-all-territories'
},
series: [{
name: 'Basemap',
dataLabels: {
enabled: true,
format: '{point.name}'
}
},
{
// Specify points using lat/lon
type: 'mappoint',
data: {
table: 'pvsoiling-table',
startRow: 1,
startColumn: 1,
endColumn: 2
},
name: 'PV',
marker: {
fillColor: 'white',
lineColor: 'black',
lineWidth: 2,
radius: 10
},
color: Highcharts.getOptions().colors[1]
}
]
});
thanks,
Shauna
You can make the following changes to your code:
At the start of your <script> section, load your HTML table data into a JavaScript array:
var mapData = [];
Highcharts.data({
table: document.getElementById('pvsoiling-table'),
startColumn: 1,
endColumn: 2,
firstRowAsNames: true,
complete: function (options) {
options.series[0].data.forEach(function (p) {
mapData.push({
lat: p[0],
lon: p[1]
});
});
//console.log(mapData);
}
});
We will refer to this mapData array later on. Here is what it contains:
[
{ "lat": 33.3, "lon": -111.67 }
]
Make changes to the series section in your Highcharts.mapChart.
series: [{
name: 'Basemap',
nullColor: '#e0f9e3',
dataLabels: {
enabled: true,
format: '{point.name}'
}},
{
// Specify points using lat/lon
data: mapData,
type: 'mappoint',
name: 'PV',
marker: {
fillColor: 'white',
lineColor: 'black',
lineWidth: 1,
radius: 3
},
color: Highcharts.getOptions().colors[1]
}
]
The key part to note is the data: mapData option. The JavaScript mapData variable is the exact array that we need to represent a set of points on the map. In our case the array only contains one point - but that's because there is only one relevant row of data in the HTML table.
My map ends up looking like this:
It looks like the marker is in or near Phoenix, AZ.
Final notes:
(a) I also adjusted the marker to have lineWidth: 1 and radius: 3 (a bit smaller).
(b) I added a document ready function around everything, to ensure the DataTable is loaded before you try to read its data.
(c) There may be a more elegant way to do this, but I followed the approach in this demo. The demo actually shows how to join 2 different sets of data - not what you need. But it does show a good approach for extracting the HTML data so it can be used in the map.
Using the the Highcharts.data({...}) approach lets you access any HTML table. But since you are using DataTables, you can choose to do the following, instead. It uses the DataTables API to access each row of data:
var mapData = [];
$('#pvsoiling-table').DataTable({
"initComplete": function(settings, json) {
var api = this.api();
api.rows().data().each(function (p) {
mapData.push({ lat: Number(p[1]), lon: Number(p[2]) });
});
// your Highcharts.mapChart() logic, in a function:
buildChart();
}
});

highcharts lollipop/dumbbell chart change position/colour of positive and negative marker values

I am trying to create a lollipop chart where some values are negative, and some are positive, either side of zero, like this:
image
However the chart seemingly only allows the marker to be on the "high" end of the chart. Is there a way to control which end has the marker ?
I'm using these chart options:
chartOptions: {
chart: {
type: 'dumbbell',
inverted: true
},
title: {
text: 'lollipop chart'
},
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: 'value'
}
},
series: [{
name: 'value',
data: [{
name: 'a',
low:0,
high:13,
}, {
name: 'b',
low:0,
high:26,
},{
name: 'c',
low:-43,
high:0
},{
name: 'd',
low:-83,
high:0
},{
name: 'e',
low:0,
high:113
}]
}]
}
The series which should be used in this case is a lollipop, but it seems that the array of objects configuration doesn't work. I reported it on the Highcharts Github issue channel, where you can follow this thread: https://github.com/highcharts/highcharts/issues/13202
As a solution in the dumbell series I suggest to find those graphics in the render callback and hide them.
Demo: https://jsfiddle.net/BlackLabel/3o7acsbt/
events: {
render() {
let chart = this;
chart.series[0].points.forEach(p => {
if (p.low >= 0){
p.lowerGraphic.hide()
} else {
p.upperGraphic.hide()
}
})
}
}
API: https://api.highcharts.com/highcharts/chart.events.render
EDIT
Under the GitHub link, the workaround showed up. Please check it, maybe will be fit better to your requirement.

Highstock Issue - Can't draw and plot chart correctly

I'm working on project to display stock information using Highstock.
Question 1:
I tried to display ohlc data using ohlc graph, high and low using areasplinerange graph, and volume using column chart.
Everything works fine, if i zoom 1m, 3m, 6m, YTD, and 1y. Here is the snapshot. link1. But if zoom to All, The graph messed up like this link2.
Am i wrong in my coding or it's bug?
Question 2:
In the same chart, I have code to change the type of graph from ohlc to line. It works fine when I zoom to 1m, 3m. Here is the snapshot link3. But it show me no line chart when i zoom to 6m, 1y, and All. Here is the snapshot link4.
How can this happen?
Thank you for your help.
The Code:
Here is the code that i used to display the chart
$.getJSON(url, function (data1) {
$.getJSON(urlprediction, function (data2) {
var ohlc = [],
volume = [],
closed = [],
forecast = [],
dataLength1 = data1.length;
dataLength2 = data2.length;
for (i = 0; i < dataLength1; i++) {
ohlc.push([
data1[i][0], // the date
data1[i][1], // open
data1[i][2], // high
data1[i][3], // low
data1[i][4] // close
]);
closed.push([
data1[i][0], // the date
data1[i][4] // close
]);
volume.push([
data1[i][0], // the date
data1[i][5] // the volume
])
}
for (i = 0; i < dataLength2; i++) {
forecast.push([
data1[i][0], // the date
data1[i][1],
data1[i][2], // close
])
}
// set the allowed units for data grouping
var groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]];
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 1
},
title: {
text: title
},
yAxis: [{
title: {
text: 'OHLC'
},
height: 360,
lineWidth: 2
}, {
title: {
text: 'Volume'
},
top: 433,
height: 100,
offset: 0,
lineWidth: 2
}],
series: [{
type: 'ohlc',
name: stockname,
data: ohlc,
}, {
type: 'areasplinerange',
name: stockname,
data: data2,
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
}]
});
});
});

Resources