Map update! 🌎

This commit is contained in:
rzmk 2021-12-24 20:36:01 -05:00
parent fe32cf5c9c
commit 519b54f2b4
9 changed files with 349 additions and 20 deletions

View file

@ -2,13 +2,14 @@
[![Webapp demo](demo.gif)](https://rzmk.github.io/iss-position-spa)
Fetches the latitude and longitude of the International Space Station (ISS) every 10 seconds and displays the position with a progress bar.
Fetches the latitude and longitude of the International Space Station (ISS) every 2 seconds and displays the live position on a map with a progress bar.
## Technologies
- [React](https://reactjs.org/)
- [TailwindCSS](https://tailwindcss.com/)
- [react-icons](https://github.com/react-icons/react-icons)
- [wheretheiss.at](https://wheretheiss.at)
- [react-icons](https://github.com/react-icons/react-icons)
- [react-simple-maps](https://github.com/zcreativelabs/react-simple-maps)
- [uiGradients](https://uigradients.com/#VisionsofGrandeur)
- [GitHub Pages](https://pages.github.com/)

BIN
demo.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 MiB

After

Width:  |  Height:  |  Size: 15 MiB

Before After
Before After

238
package-lock.json generated
View file

@ -16,6 +16,7 @@
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"react-scripts": "5.0.0",
"react-simple-maps": "^2.3.0",
"web-vitals": "^2.1.2"
},
"devDependencies": {
@ -5666,6 +5667,91 @@
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="
},
"node_modules/d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
"dependencies": {
"internmap": "^1.0.0"
}
},
"node_modules/d3-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
"integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
},
"node_modules/d3-dispatch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
"integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
},
"node_modules/d3-drag": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz",
"integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==",
"dependencies": {
"d3-dispatch": "1 - 2",
"d3-selection": "2"
}
},
"node_modules/d3-ease": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz",
"integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ=="
},
"node_modules/d3-geo": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.2.tgz",
"integrity": "sha512-8pM1WGMLGFuhq9S+FpPURxic+gKzjluCD/CHTuUF3mXMeiCo0i6R0tO1s4+GArRFde96SLcW/kOFRjoAosPsFA==",
"dependencies": {
"d3-array": "^2.5.0"
}
},
"node_modules/d3-interpolate": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
"integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
"dependencies": {
"d3-color": "1 - 2"
}
},
"node_modules/d3-selection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz",
"integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA=="
},
"node_modules/d3-timer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz",
"integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA=="
},
"node_modules/d3-transition": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz",
"integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==",
"dependencies": {
"d3-color": "1 - 2",
"d3-dispatch": "1 - 2",
"d3-ease": "1 - 2",
"d3-interpolate": "1 - 2",
"d3-timer": "1 - 2"
},
"peerDependencies": {
"d3-selection": "2"
}
},
"node_modules/d3-zoom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz",
"integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==",
"dependencies": {
"d3-dispatch": "1 - 2",
"d3-drag": "2",
"d3-interpolate": "1 - 2",
"d3-selection": "2",
"d3-transition": "2"
}
},
"node_modules/damerau-levenshtein": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz",
@ -8421,6 +8507,11 @@
"node": ">= 0.4"
}
},
"node_modules/internmap": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz",
"integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="
},
"node_modules/ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@ -13421,6 +13512,22 @@
}
}
},
"node_modules/react-simple-maps": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/react-simple-maps/-/react-simple-maps-2.3.0.tgz",
"integrity": "sha512-IZVeiPSRZKwD6I/2NvXpQ2uENYGDGZp8DvZjkapcxuJ/LQHTfl+Byb+KNgY7s+iatRA2ad8LnZ3AgqcjziCCsw==",
"dependencies": {
"d3-geo": "^2.0.1",
"d3-selection": "^2.0.0",
"d3-zoom": "^2.0.0",
"topojson-client": "^3.1.0"
},
"peerDependencies": {
"prop-types": "^15.7.2",
"react": "^16.8.0 || 17.x",
"react-dom": "^16.8.0 || 17.x"
}
},
"node_modules/readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
@ -14947,6 +15054,24 @@
"node": ">=0.6"
}
},
"node_modules/topojson-client": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz",
"integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
"dependencies": {
"commander": "2"
},
"bin": {
"topo2geo": "bin/topo2geo",
"topomerge": "bin/topomerge",
"topoquantize": "bin/topoquantize"
}
},
"node_modules/topojson-client/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"node_modules/tough-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
@ -20278,6 +20403,88 @@
}
}
},
"d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
"requires": {
"internmap": "^1.0.0"
}
},
"d3-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
"integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
},
"d3-dispatch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
"integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
},
"d3-drag": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz",
"integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==",
"requires": {
"d3-dispatch": "1 - 2",
"d3-selection": "2"
}
},
"d3-ease": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz",
"integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ=="
},
"d3-geo": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.2.tgz",
"integrity": "sha512-8pM1WGMLGFuhq9S+FpPURxic+gKzjluCD/CHTuUF3mXMeiCo0i6R0tO1s4+GArRFde96SLcW/kOFRjoAosPsFA==",
"requires": {
"d3-array": "^2.5.0"
}
},
"d3-interpolate": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
"integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
"requires": {
"d3-color": "1 - 2"
}
},
"d3-selection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz",
"integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA=="
},
"d3-timer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz",
"integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA=="
},
"d3-transition": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz",
"integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==",
"requires": {
"d3-color": "1 - 2",
"d3-dispatch": "1 - 2",
"d3-ease": "1 - 2",
"d3-interpolate": "1 - 2",
"d3-timer": "1 - 2"
}
},
"d3-zoom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz",
"integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==",
"requires": {
"d3-dispatch": "1 - 2",
"d3-drag": "2",
"d3-interpolate": "1 - 2",
"d3-selection": "2",
"d3-transition": "2"
}
},
"damerau-levenshtein": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz",
@ -22294,6 +22501,11 @@
"side-channel": "^1.0.4"
}
},
"internmap": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz",
"integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="
},
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@ -25749,6 +25961,17 @@
"workbox-webpack-plugin": "^6.4.1"
}
},
"react-simple-maps": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/react-simple-maps/-/react-simple-maps-2.3.0.tgz",
"integrity": "sha512-IZVeiPSRZKwD6I/2NvXpQ2uENYGDGZp8DvZjkapcxuJ/LQHTfl+Byb+KNgY7s+iatRA2ad8LnZ3AgqcjziCCsw==",
"requires": {
"d3-geo": "^2.0.1",
"d3-selection": "^2.0.0",
"d3-zoom": "^2.0.0",
"topojson-client": "^3.1.0"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
@ -26878,6 +27101,21 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
"topojson-client": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz",
"integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
"requires": {
"commander": "2"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
}
}
},
"tough-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",

View file

@ -12,6 +12,7 @@
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"react-scripts": "5.0.0",
"react-simple-maps": "^2.3.0",
"web-vitals": "^2.1.2"
},
"scripts": {

View file

@ -35,3 +35,18 @@
transform: rotate(360deg);
}
}
/* Small only */
@media screen and (max-width: 65em) {
h1 + svg {
display: none;
}
}
/* Medium and up */
@media screen and (min-width: 65em) {
h1 + svg {
display: block;
margin-bottom: -1.5em;
}
}

View file

@ -1,6 +1,7 @@
// import logo from "../logo.svg";
import React, { useState, useEffect } from "react";
import { AiFillGithub } from "react-icons/ai";
import Map from "./components/Map";
import Coordinates from "./components/Coordinates";
import ProgressBar from "./components/ProgressBar";
import "./App.css";
@ -15,38 +16,27 @@ function App() {
"https://api.wheretheiss.at/v1/satellites/25544"
);
const data = await resp.json();
await setLongitude(String(data.longitude).slice(0, 7));
await setLatitude(String(data.latitude).slice(0, 7));
setLongitude(String(data.longitude));
setLatitude(String(data.latitude));
setProgress(0);
}
useEffect(() => {
fetchISSData();
setInterval(fetchISSData, 10000);
setInterval(fetchISSData, 2000);
setInterval(() => {
setProgress((prev) => prev + 1);
setProgress((prev) => prev + 5);
}, 100);
}, []);
return (
<div className="App">
<header className="App-header">
{/* <img src={logo} className="App-logo" alt="logo" /> */}
<h1 className="text-4xl sm:text-6xl">
International Space Station Position
</h1>
<table className="my-8 text-3xl sm:text-4xl">
<tbody>
<tr>
<td className="text-left">Latitude:</td>
<td className="text-right">{latitude}</td>
</tr>
<tr>
<td className="text-left">Longitude:</td>
<td className="text-right pl-10">{longitude}</td>
</tr>
</tbody>
</table>
<Map latitude={latitude} longitude={longitude} />
<Coordinates latitude={latitude} longitude={longitude} />
<ProgressBar progress={progress} />
<a
href="https://github.com/rzmk/iss-position-spa"

View file

@ -0,0 +1,32 @@
import React, { useState, useEffect } from "react";
function Coordinates({ latitude, longitude }) {
const [smallScreen, setSmallScreen] = useState(false);
useEffect(() => {
if (window.screen.width < 480) setSmallScreen(true);
else setSmallScreen(false);
}, [window.screen.width]);
return (
<div>
<table className="my-8 text-3xl sm:text-4xl">
<tbody>
<tr>
<td className="text-left">Latitude:</td>
<td className="text-right">
{smallScreen ? latitude.slice(0, 7) : latitude}
</td>
</tr>
<tr>
<td className="text-left">Longitude:</td>
<td className="text-right pl-10">
{smallScreen ? longitude.slice(0, 7) : longitude}
</td>
</tr>
</tbody>
</table>
</div>
);
}
export default Coordinates;

3
src/components/Map.css Normal file
View file

@ -0,0 +1,3 @@
.satellite {
margin-right: 2rem;
}

49
src/components/Map.js Normal file
View file

@ -0,0 +1,49 @@
import React from "react";
import { IconContext } from "react-icons";
import { FaSatellite } from "react-icons/fa";
import {
ComposableMap,
Geographies,
Geography,
Graticule,
Marker,
Sphere,
} from "react-simple-maps";
import "./Map.css";
const geoUrl =
"https://raw.githubusercontent.com/zcreativelabs/react-simple-maps/master/topojson-maps/world-110m.json";
const Map = ({ latitude, longitude }) => {
// Icon alignment offset fix
const newLong = String(Number(longitude) - 2.7);
const newLat = String(Number(latitude) + 5);
return (
<ComposableMap projection="geoEqualEarth" width="2400">
<Graticule stroke="rgba(255, 255, 255, 0.5)" />
<Sphere stroke="#FF5533" strokeWidth={2} />
<Geographies geography={geoUrl}>
{({ geographies }) =>
geographies.map((geo) => (
<Geography
key={geo.rsmKey}
geography={geo}
fill="#DDD"
stroke="#FFF"
/>
))
}
</Geographies>
<Marker coordinates={[newLong, newLat]}>
<FaSatellite color="red" />
</Marker>
{/* Debug for exact coordinates comparison to above
<Marker coordinates={[longitude, latitude]}>
<circle r={8} stroke="red" stroke-width={2} fill="white" />
</Marker> */}
</ComposableMap>
);
};
export default Map;