Earthquake Realtime BMKG
Akhirnya saya membuatnya, project ini adalah impian saya dulu ketika tertarik dengan kegempaan waktu kuliah dulu, dengan perawalan menyukai dasar ilmu struktur geologi, tentu juga sedimentologi, karena stratigrafi akan menjadi nilai 0 jika tanpa struktur geologi, bumi sudah tua, deformasi dimana-dimana, baik natural maupun karena tingkah kita (manusia), ya masa-masa deformasi akan terus berlanjut sampai memang kala waktu yang menghentikannya. Ini bukan puisi, melainkan awalan dalam membuat Personal project Earthquake Realtime BMKG.
Requirement
Untuk mengawali project ini dibutuhkan beberapa tools diantaranya:
- NodeJS
- Code editor
- Your head 🧄
Untuk tech stack yang digunakan sebagai berikut, beserta kegunaannya:
- ReactJS sebagai framework
- OpenLayers sebgai main library mapping
- RLayers sebagai support OpenLayers di dalam React
- React-timeseries-charts sebagai library timeseries untuk react
- React-Query sebagai state dan fetching management
- Moment sebagai support time library
- TailwindCSS sebagai support library style css
- API dari BMKG itu sendiri yang open public
Perlu dijelaskan disini, API dari BMKG data yang tersedia hanya menampilkan kegempaan diatas 5 Magnitudo, kegempaan yang di bawah itu tidak tersedia. Dan project ini hanya untuk dekstop friendly, karena timeseries dan custom feature di dalamnya sedikit berat, dan butuh penyesuaian lagi untuk mendisplay beberapa feature didalamnya
Getting Started
Inisialisasi directory pada laptop anda dan jalankan create react app dengan diikuti nama project setelahnya
npx create react-app earthquake-bmkg
Initialisasi Map
Tambahkan reference dan center untuk map
const mapRef = useRef(null);
const [centerMap, setCenterMap] = useState({ center: fromLonLat([119.8917871, 0.838468]), zoom: 5 });
Buat file MapRender.js
, Masukan pada props yang disediakan di RMap
<div className='w-screen h-[100svh]'>
<RMap
className='relative w-screen h-screen z-0 ol-control'
initial={props.centerMap}
ref={props.mapRef}
onPointerDrag={(e) => {
return (
<div>
<RInteraction.RModify snapTolerance={0.001} />
</div>
)
}}
>
{/* option tile layer pertama */}
<ROSM />
{/* option tile layer kedua */}
<RLayerTile
useInterimTilesOnError={true}
url='YOUR_URL_FROM_MAP_TILES-/{z}/{x}/{y}.png?'
attributions='this site created by <a href="https://www.maptiler.com/copyright/" target="_blank">'
className="-z-0"
/>
{props.children}
<RControl.RFullScreen />
<RControl.RScaleLine />
<RControl.RAttribution />
<RControl.RZoom />
</RMap>
</div>
Initialisasi Layer Maps
Add Layers pada children component MapRender, in here I use React.memo to define component on App.js
const [eqView, setEqView] = useState(true);
const [faultView, setFaultView] = useState(true);
{eqView && (
<EqMemo
eqLayer={eqLayer} // state of data from react-query
isStale={isStale} // state of stale from react-query
isLoading={isLoading} // state of loading from react-query
mapRef={mapRef} // ref maps
setCenterMap={setCenterMap} // for handling zoom
setLayers={setLayers} // for save layer select on state
setForceInfoLayer={setForceInfoLayer} // for triger open sidebar
/>
)}
{faultView && (
<FaultMemo /> // layer using geojson on public directory
)}
Berikut untuk cara mendeskripsikan data geojson untuk di integrasikan menjadi feature
dari OpenLayers
, pada kode dibawah ini kita membuat definisi class Feature dengan data geojson yang kita miliki
const data = eqLayer?.features
const eqFeatures = Object.keys(data ?? {}).map(
(key) =>
new Feature({
geometry: new Point(
fromLonLat(data[key].geometry.coordinates),
),
id: data[key].properties.id,
mag: data[key].properties.mag,
place: data[key].properties.place,
time: data[key].properties.time,
depth: data[key].properties.depth,
status: data[key].properties.status,
fase: data[key].properties.fase
}),
);
Initialisasi Vector Mapping With Multiple Style
Pada file EqMemo
sebagai berikut:
{eqFeatures.map((val) => (
<RLayerVector
key={val.get("id")}
zIndex={10}
onClick={(e) => setLayers(e)}
>
<RStyle.RStyle ref={style} zIndex={val.get('depth') ? val.get('depth') + 15 : 5}>
<RStyle.RCircle
radius={
parseFloat(val.get('mag')) > 7 ? parseFloat(val.get('mag')) + 5
: parseFloat(val.get('mag')) > 6 ? parseFloat(val.get('mag')) + 4
: parseFloat(val.get('mag')) > 5.5 ? parseFloat(val.get('mag')) + 2 : 4}>
<RStyle.RFill color={parseFloat(val.get('depth')) > 1000 ? 'purple'
: parseFloat(val.get('depth')) > 500 ? 'green'
: parseFloat(val.get('depth')) > 100 ? 'yellow'
: parseFloat(val.get('depth')) > 30 ? 'blue' :
'red'} />
<RStyle.RStroke color="#2cb5db" width={1} />
</RStyle.RCircle>
</RStyle.RStyle>
<RFeature
feature={val}
onClick={(e) => {
e.map.getView().fit(e.target.getGeometry().getExtent(), {
duration: 300,
maxZoom: 10
})
setLayers(e)
setForceInfoLayer(true)
}}
>
</RFeature>
</RLayerVector>
))}
Initialisasi Vector GeoJSON file static
Dan pada file FaultMemo sebagai berikut
<RLayerVector
zIndex={10}
url='/file/faults.geojson' // ditujukan file geojson yang ada di public directory
format={
new GeoJSON({
featureProjection: "EPSG:3857",
dataProjection: "EPSG:4326",
})
}
>
<RStyle.RStyle ref={style}>
<RStyle.RStroke color="red" width={1} />
</RStyle.RStyle>
</RLayerVector >
Done..!!
Semoga tulisan ini bermanfaat, adapun untuk demo applikasinya anda bisa akses langsung pada laman berikut https://earthquake-maps.vercel.app/