Customize Tropical Cyclone Markers

Customize a tropical-cyclones point layer provided by the Tropical module. The custom style will result in displaying storm category symbols and valid dates/times along the forecast track instead of basic points.

Custom tropical cyclone marker styling example
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no'/>

    <title>AerisWeather JavaScript SDK - Tropical Systems w/Custom Styles</title>
    <script defer src="https://cdn.aerisapi.com/sdk/js/latest/aerisweather.min.js"></script>
    <link rel="stylesheet" href="https://cdn.aerisapi.com/sdk/js/latest/aerisweather.css">
    
    <style>
        html, body {
            height: 100%;
            margin: 0;
            padding: 0;
            width: 100%;
        }
        #map {
            height: 100%;
            width: 100%;
        }
    </style>

</head>
<body>

<div id="map"></div>

<script>

    window.onload = () => {

        const aeris = new AerisWeather('CLIENT_ID', 'CLIENT_SECRET');
        const utils = aeris.utils;

        aeris.views().then(views => {
            const map = new views.InteractiveMap(document.getElementById('map'), {
                center: {
                    lat: 39.0,
                    lon: -95.5
                },
                zoom: 4,
                layers: 'alerts,radar-est'
            });

            map.on('ready', () => {
                aeris.modules().then((modules) => {
                    modules.tropical.utils().then((tropUtils) => {

                        // utility functions for styling
                        const getMarkerDate = (data) => {
                            let tzName = utils.get(data, 'profile.tz', 'UTC');
                            let dt = luxon.DateTime.fromISO(utils.get(data,'dateTimeISO')).setZone(tzName);
                            return dt.toFormat('h a ccc ZZZZ');
                        };

                        const getStormMarkerConfig = (data) => {
                            const {lat} = utils.get(data, 'loc');
                            const type = utils.get(data, 'details.stormCat');
                            const isCurrent = data.isCurrent;
                            const isForecast = data.isForecast;
                            const flipped = lat < 0 && tropUtils.flipForSouthernLat(type);

                            if (isCurrent || isForecast) {
                                const catTextStyle = {
                                    value: (type === 'STY') ? 'S': type.replace(/[^\d]/g, ''),
                                    anchor: 'start',
                                    position: 'center',
                                    translate: {
                                        y: -2
                                    },
                                    size: 14,
                                    color: '#ffffff',
                                    autosize: false
                                };
                                const nameTextStyle = {
                                    value: getMarkerDate(data),
                                    anchor: 'start',
                                    translate: {
                                        y: 22
                                    },
                                    size: 11,
                                    color: '#222222',
                                    stroke: {
                                        color: '#ffffff',
                                        width: 2
                                    },
                                    autosize: false
                                }

                                let styles = {
                                    className: 'marker-tropicalcyclone',
                                    svg: {
                                        image: {
                                            url: (flipped && type === 'TD') ? tropUtils.icon(`${type}-flipped`): tropUtils.icon(type),
                                            size: [25, 25],
                                            transform: (flipped && type !== 'TD') ? 'scale(-1, 1) translate(-80, 0)': ''
                                        },
                                        text: [catTextStyle, nameTextStyle]
                                    },
                                    size: [80, 60],
                                    zIndex: 50
                                };

                                if (isCurrent) {
                                    styles = utils.extend({}, styles, {
                                        svg: {
                                            image: {
                                                size: [34, 34]
                                            },
                                            text: [
                                                utils.extend({}, catTextStyle, {
                                                    translate: {
                                                        y: -3
                                                    },
                                                    size: 20
                                                }),
                                                utils.extend({}, catTextStyle, {
                                                    value: utils.get(data, 'details.stormShortName'),
                                                    size: 16,
                                                    color: '#222222',
                                                    translate: {
                                                        y: 22
                                                    },
                                                    stroke: {
                                                        color: '#ffffff',
                                                        width: 3
                                                    }
                                                })
                                            ]
                                        },
                                        size: [80, 80]
                                    });
                                }

                                return styles;
                            }

                            return {
                                className: 'marker-tropicalcyclone',
                                svg: {
                                    shape: {
                                        type: 'circle',
                                        fill: {
                                            color: tropUtils.color(type)
                                        },
                                        stroke: {
                                            color: '#ffffff',
                                            width: 2
                                        },
                                        size: [14, 14]
                                    },
                                    text: data.label ? {
                                        value: utils.get(data, 'details.stormShortName'),
                                        anchor: 'start',
                                        translate: {
                                            y: 12
                                        },
                                        autosize: false
                                    }: null
                                },
                                size: data.label ? [60, 40]: [14, 14],
                                zIndex: data.label ? 50: null
                            };
                        };

                        map.addModule(modules.tropical.Breakpoints);
                        map.addModule(modules.tropical.Systems, {
                            style: {
                                marker: (data) => getStormMarkerConfig(data, aeris.utils),
                                polyline: {
                                    stroke: {
                                        color: '#4685D0',
                                        width: 3,
                                        dashArray: '10 7 10 7'
                                    }
                                },
                                polygon: {
                                    fill: {
                                        color: '#ffffff',
                                        opacity: 0
                                    },
                                    stroke: {
                                        color: '#666666',
                                        width: 2,
                                        opacity: 0.7

                                    }
                                },

                            }

                        });
                    });
                });
            });
        });
    };

</script>
<script src="https://cdn.jsdelivr.net/npm/luxon@1.24.1/build/global/luxon.min.js"></script>

</body>
</html>

Last modified: November 16, 2020