AlexisGado
Posts: 3
Joined: Mon Nov 29, 2021 3:11 pm

Automatic conversion from Lat/Lon to x y in mapline series

Hello !

I am trying to plot vertices and edges on a map (geojson) in a React app. I am using highcharts 9.3.0 et highcharts-react-official 3.1.0.

The code is a bit messy but the important part is the NewSeries array in the useEffect hook.
For the mappoint series to work corrrectly with lat lon data, I had to load proj4js. It is working but I thought proj4 was not necessary anymore (according to https://www.highcharts.com/docs/maps/latlon).
The main issue is in the mapline series. I am not able to get the behavior of this example https://jsfiddle.net/gh/get/library/pur ... -geometry/ and I need to do this messy manual conversion using Chart.fromLatLonToPoint.
I probably missed something in the documentation, I hope it was not too obvious !

Code: Select all

const defaultSeries: Array<SeriesOptionsType> = [
    {
        type: 'map',
        mapData: zbMap,
        data: data,
        name: 'Region',
        states: {
            hover: {
                color: '#F0851B'
            }
        },
    },
]

const optionsDefault: Highcharts.Options = {
    title: {
        text: '' // TODO : add configuration
    },
    credits: {
        enabled: false,
    },
    plotOptions: {
        series: {
            states: {
                inactive: {
                    opacity: 1
                }
            }
        }
    },
    legend: {
        enabled: false,
    },
    tooltip: {
        enabled: false,
    },
    mapNavigation: {
        enabled: true,
        buttonOptions: {
            verticalAlign: 'bottom'
        }
    },
    colorAxis: {
        min: 0
    },
    series: defaultSeries,
}

export const MapLsWidget = ({ widgetProp, lsService }: { widgetProp: LsWidgetState; lsService: LSService }) => {
    const chartRef = useRef<{ chart: Chart; container: React.RefObject<HTMLDivElement> }>(null);
    const [optionsState, setOptionsState] = useState(optionsDefault);

    useEffect(() => {
        chartRef.current?.chart?.reflow();
    }, [widgetProp]);

    useEffect(() => {
        if (lsService.isAvailable && isMapLsWidgetInfo(widgetProp.widgetInfos)) {
            const verticesDataName = widgetProp.widgetInfos.vertices;
            const edgesDataName = widgetProp.widgetInfos.edges;
            const mapData = lsService.getVerticesAndEdgesCoordinates(verticesDataName, edgesDataName);

            if (mapData) {
                const newSeries = JSON.parse(JSON.stringify(defaultSeries)) as Array<SeriesOptionsType>;
                mapData.vertices ? newSeries.push({
                    type: 'mappoint',
                    name: 'testV',
                    data: mapData.vertices,
                    color: '#550000',
                    colorAxis: false,
                    zIndex: 3,
                }) : null;
                mapData.edges ? newSeries.push({
                    type: 'mapline',
                    name: 'testE',
                    data: mapData.edges.map<SeriesMaplineDataOptions>((edge) => ({
                        geometry: {
                            type: 'LineString',
                            coordinates: [
                                Object.values(chartRef.current?.chart.fromLatLonToPoint({lat: edge.p1.lat, lon: edge.p1.lon}) ?? {}),
                                Object.values(chartRef.current?.chart.fromLatLonToPoint({lat: edge.p2.lat, lon: edge.p2.lon}) ?? {}),
                            ],
                        },
                    })),
                    color: '#00FF99',
                    lineWidth: 2,
                    colorAxis: false,
                }) : null;
                // console.log(" ",newSeries)
                setOptionsState((old) => {
                    return {
                        ...old,
                        series: newSeries,
                    };
                });
            }
        }
    }, [widgetProp.widgetInfos, lsService]);
    
    return (
        <div className="chart-container-1">
            <HighchartsReact
                id={widgetProp?.i}
                highcharts={Highcharts}
                options={optionsState}
                containerProps={{ className: 'chart-container-2' }}
                ref={chartRef}
                constructorType={"mapChart"}
            />
        </div>
    );
};
mateusz.b
Posts: 2006
Joined: Tue Jul 13, 2021 11:34 am

Re: Automatic conversion from Lat/Lon to x y in mapline series

Hello AlexisGado,

Welcome to our forum and thanks for contacting us with your question!

In the example it is possible to use Lat/Lon values with mapline series because the demo is based on TopoJSON and it is a general rule here. If you want to use lat/lon values then you either have to use TopoJSON or GeoJSON with proj4js. So you didn't miss anything, the conversions might look a bit messy but unless you have map data TopoJSON form, you have to use proj4js.

Let me know if you have any further questions!
Regards!
Mateusz Bernacik
Highcharts Developer

Return to “Highcharts Maps”