DEV Community

Shriji
Shriji

Posted on

Making ISS 🛰️ tracker using Leaflet and Svelte

This weekend I built ISS Tracker using leaflet a map provider without API or paywalls and there aren't many examples with Svelte implementation.

Leaflet has excellent documentation for JS most things can be achieved with just JS.

ISS

Prerequisites:

  1/ Svelte starter template (https://svelte.dev/)
  2/ ISS API (http://open-notify.org/Open-Notify-API/)
  3/ Leaflet via NPM (https://www.npmjs.com/package/leaflet)
  4/ *some amount of patience.*
Enter fullscreen mode Exit fullscreen mode

Using the boilerplate fetch with svelte and obtaining the json data from the API.

const URL = "http://api.open-notify.org/iss-now.json"
async function fetchInfo() {
    const res = await fetch(URL).then(async data => {
    let d = await data.json();
    lat = d.iss_position.latitude
    lon = d.iss_position.longitude
    console.log({lat,lon})
    marker.setLatLng([lat, lon]).update();
    m.panTo([lat, lon]);
    })
    setTimeout(fetchInfo,5000)
    }
Enter fullscreen mode Exit fullscreen mode

This gives us latitude and longitude that which we can plot on the map. The setTimeout() is to set positions of the ISS every 5 seconds 😉.

Now leaflet will test your patience basically it is a mash of several tutorials here https://leafletjs.com/examples.html 😅

Here is a small snippet that will help you thanks to this post
The base config can be done like this

    import * as L from 'leaflet';

//fancy custom icon
    var ISS_Icon = L.icon({
        iconUrl: './favicon.png',
        iconSize: [48, 48], // size of the icon
    });

    function createMap(container) {
        m = L.map(container).setView([0, 0], 2);
        marker  = L.marker(m.getCenter(), {icon: greenIcon}).addTo(m)
        L.tileLayer(
            'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
                attribution: `&copy;<a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>`,
                subdomains: 'abcd',
                maxZoom: 14,
        }
        ).addTo(m);
        return m;
    }
    function mapAction(container) {
        map = createMap(container);
        return {
            destroy: () => {
                map.remove();
            },
        };
    }
Enter fullscreen mode Exit fullscreen mode

Because leaflet can't repaint itself you will find some grey patches without it a combination of <svelte:window> calling the resizeMap() will fix it.

    function resizeMap() {
        if (map) {
            map.invalidateSize();
        }
    }

<svelte:window on:resize={resizeMap} />

<div style="height:600px;width:100%" use:mapAction /> //invokes the map 
Enter fullscreen mode Exit fullscreen mode

Now let's consume the other good juicy stuff from that API. ISS crosses above your location from here obtain and list next 5 passes from the obtained from Using the Geolocation API and the API has CORS... Hmm... 🤔🤔🤔 We can use https://cors-anywhere.herokuapp.com/ before the URL and get the data 😝

let warntext = 'Please allow location access to know when ISS will pass your location.'

    function getLocation() {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(showPosition);
        } else {
            console.log("Geolocation is not supported by this browser / Not shared")
        }
    }

    function showPosition(position) {
        console.log(position.coords.latitude, position.coords.longitude);
        fetchPasses(position.coords.latitude, position.coords.longitude)
    }
    getLocation()
    let ISSPass = '';
    async function fetchPasses(lt, ln) {
        warntext = 'loading...'
        const res = await fetch(`https://cors-anywhere.herokuapp.com/${passes}lat=${lt}&lon=${ln}`).then(
    async data => {
            let d = await data.json();
            ISSPass = await d.response;
            warntext = 'Check below for the passes!'

        })

    }
Enter fullscreen mode Exit fullscreen mode

And in the svelte we can populate like this

<span>{warntext}</span>
    <ul>
        {#each ISSPass as item} 
            <li>
                {new Date(item.risetime*1000).toLocaleString()} <br>
            </li>
        {/each}
    </ul>
Enter fullscreen mode Exit fullscreen mode

Thanks for reading my post it's little longer than my usual posts.

Here is the repo.

https://github.com/peopledrivemecrazy/svelte-iss

Enjoy.

Discussion (0)