kepler-showcase / locations.html
thanthamky's picture
Upload 47 files
ac218ce verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Disaster Risk and Impact Analysis</title>
<script src="static/js/deckgl@9.0.33.min.js"></script>
<script src="static/js/maplibre-gl@3.0.0.js"></script>
<link href="static/css/maplibre-gl@3.0.0.css" rel="stylesheet" />
<script src="static/js/tailwind@3.4.5.js"></script>
<script src="static/js/chart.js"></script>
<script src="static/js/popper.min.js"></script>
<script src="static/js/tippy-bundle.umd.min.js"></script>
<link rel="stylesheet" href="static/css/font-awesome@all.min.css" />
<style>
html,
body {
height: 100%;
margin: 0;
}
#map {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<!-- Floating Box for Charts -->
<div
class="absolute left-4 top-4 h-9/10 bottom-4 w-2/5 p-6 bg-white backdrop-blur-sm bg-opacity-60 shadow-lg overflow-y-auto z-10 rounded-2xl"
>
<h1 class="text-2xl font-bold mb-4 text-center">Location Insight</h1>
<!-- STATISTICS -->
<h1 class="text-l font-bold mb-4">Statistic</h1>
<div class="flex flex-col space-y-4 w-full">
<div
class="bg-white text-black p-6 rounded-xl shadow-md flex items-center justify-between"
>
<div class="flex items-center space-x-4">
<div class="icon bg-gray-200 p-2 rounded-full mr-4">
<img
src="static/icon/pin.png"
alt="Icon 2"
class="h-6 w-6 rounded-full"
/>
</div>
<h2 class="text-xl font-bold">Locations</h2>
</div>
<span class="text-2xl font-bold">104</span>
</div>
</div>
<!-- LAYER CONTROL -->
<h2 class="text-l font-bold mt-8 mb-4">Show Disaster Intensity</h2>
<div id="boxContainer" class="grid grid-cols-3 gap-4 mt-4">
<div
class="box flex items-center p-4 border rounded-lg cursor-pointer transition-all duration-300 bg-white"
data-id="wind"
>
<div class="icon bg-gray-200 p-2 rounded-full mr-4">
<img
src="static/icon/wind.png"
alt="Icon 2"
class="h-6 w-6 rounded-full"
/>
</div>
<h1 class="text-lg font-semibold">Wind</h1>
</div>
<div
class="box flex items-center p-4 bg-white border rounded-lg cursor-pointer transition-all duration-300"
data-id="flood"
>
<div class="icon bg-gray-200 p-2 rounded-full mr-4">
<img
src="static/icon/flood.png"
alt="Icon 2"
class="h-6 w-6 rounded-full"
/>
</div>
<h1 class="text-lg font-semibold">Flood</h1>
</div>
<div
class="box flex items-center p-4 bg-white border rounded-lg cursor-pointer transition-all duration-300"
data-id="pm"
>
<div class="icon bg-gray-200 p-2 rounded-full mr-4">
<img
src="static/icon/pm.png"
alt="Icon 2"
class="h-6 w-6 rounded-full"
/>
</div>
<h1 class="text-lg font-semibold">Air Pollution</h1>
</div>
</div>
<!-- Top 5 Location Impact to Wind -->
<h2 class="text-l font-bold mt-8 mb-4">
Top 5 Locations Most Affected by Wind
</h2>
<div
class="w-full max-w-4xl backdrop-blur-sm shadow-lg rounded-xl p-4 overflow-x-auto"
>
<table class="min-w-full table-auto">
<thead>
<tr class="bg-gray-200 text-left">
<th class="p-4 font-bold text-gray-600">Top</th>
<th class="p-4 font-bold text-gray-600">Branch</th>
<th class="p-4 font-bold text-gray-600">Score</th>
</tr>
</thead>
<tbody>
<tr class="border-b cursor-pointer hover:bg-red-400 bg-red-300">
<td class="p-4">1</td>
<td class="p-4">HomePro Phetchabun Branch</td>
<td class="p-4">14.04</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-red-400 bg-red-200">
<td class="p-4">2</td>
<td class="p-4">Home Pro Chiang Rai</td>
<td class="p-4">13.52</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-red-400 bg-red-100">
<td class="p-4">3</td>
<td class="p-4">HomePro Nakhon Si Thammarat</td>
<td class="p-4">8.687</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-red-400">
<td class="p-4">4</td>
<td class="p-4">Homepro Chaiyaphum</td>
<td class="p-4">7.845</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-red-400">
<td class="p-4">5</td>
<td class="p-4">HomePro (San Sai)</td>
<td class="p-4">6.311</td>
</tr>
</tbody>
</table>
</div>
<!-- Top 5 Location Impact to Flood -->
<h2 class="text-md font-bold mt-8 mb-4">
Top 5 Locations Most Affected by Flood
</h2>
<div
class="w-full max-w-4xl backdrop-blur-sm shadow-lg rounded-xl p-4 overflow-x-auto"
>
<table class="min-w-full table-auto">
<thead>
<tr class="bg-gray-200 text-left">
<th class="p-4 font-bold text-gray-600">Top</th>
<th class="p-4 font-bold text-gray-600">Branch</th>
<th class="p-4 font-bold text-gray-600">Score</th>
</tr>
</thead>
<tbody>
<tr class="border-b cursor-pointer hover:bg-blue-400 bg-blue-300">
<td class="p-4">1</td>
<td class="p-4">HomePro Nakhon Si Thammarat</td>
<td class="p-4">8.687</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-blue-400 bg-blue-200">
<td class="p-4">2</td>
<td class="p-4">HomePro (San Sai)</td>
<td class="p-4">6.311</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-blue-400 bg-blue-100">
<td class="p-4">3</td>
<td class="p-4">Home Pro (Chiang Mai)</td>
<td class="p-4">8.472</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-blue-400">
<td class="p-4">4</td>
<td class="p-4">Home Pro (Chiang Mai Hangdong)</td>
<td class="p-4">7.006</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-blue-400">
<td class="p-4">5</td>
<td class="p-4">HomePro </td>
<td class="p-4">4.392</td>
</tr>
</tbody>
</table>
</div>
<!-- Top 5 Location Impact to PM -->
<h2 class="text-l font-bold mt-8 mb-4">
Top 5 Locations Most Affected by Air Pollution
</h2>
<div
class="w-full max-w-4xl backdrop-blur-sm shadow-lg rounded-xl p-4 overflow-x-auto"
>
<table class="min-w-full table-auto">
<thead>
<tr class="bg-gray-200 text-left">
<th class="p-4 font-bold text-gray-600">Top</th>
<th class="p-4 font-bold text-gray-600">Branch</th>
<th class="p-4 font-bold text-gray-600">Score</th>
</tr>
</thead>
<tbody>
<tr class="border-b cursor-pointer hover:bg-gray-400 bg-gray-300">
<td class="p-4">1</td>
<td class="p-4">HomePro </td>
<td class="p-4">4.392</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-gray-400 bg-gray-200">
<td class="p-4">2</td>
<td class="p-4">Home Pro (Ayutthaya)</td>
<td class="p-4">1.467</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-gray-400 bg-gray-100">
<td class="p-4">3</td>
<td class="p-4">Home Pro the distribution center</td>
<td class="p-4">1.130</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-gray-400">
<td class="p-4">4</td>
<td class="p-4">HomePro Rangsit Klong Si</td>
<td class="p-4">1.277</td>
</tr>
<tr class="border-b cursor-pointer hover:bg-gray-400">
<td class="p-4">5</td>
<td class="p-4">Home Pro (Future Park Rangsit)</td>
<td class="p-4">1.379</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Fullscreen Map -->
<div id="map"></div>
<!--img
src="static/icon/logo.png"
alt="Top-right image"
class="absolute top-0 right-0 w-48 p-4"
/-->
<a href="index.html">
<img
src="static/icon/home.png"
id="goHome"
class="absolute bg-white backdrop-blur-sm bg-opacity-60 rounded-xl shadow-lg top-4 right-4 w-12 p-4 hover:bg-opacity-100 hover:cursor-pointer"
/>
</a>
<a href="analytics.html">
<img
src="static/icon/radar.png"
id="goOverView"
class="absolute bg-white backdrop-blur-sm bg-opacity-60 rounded-xl shadow-lg top-20 right-4 w-12 p-4 hover:bg-opacity-100 hover:cursor-pointer"
/>
</a>
<a href="locations.html">
<img
src="static/icon/location.png"
id="goLocation"
class="absolute bg-white backdrop-blur-sm bg-opacity-60 rounded-xl shadow-lg top-36 right-4 w-12 p-4 hover:bg-opacity-100 hover:cursor-pointer"
/>
</a>
<a href="forecast.html">
<img
src="static/icon/forecast.png"
id="goForecast"
class="absolute bg-white backdrop-blur-sm bg-opacity-60 rounded-xl shadow-lg top-52 right-4 w-12 p-4 hover:bg-opacity-100 hover:cursor-pointer"
/>
</a>
<img
src="static/icon/extent.png"
id="resetViewButton"
class="absolute bg-white backdrop-blur-sm bg-opacity-60 rounded-xl shadow-lg bottom-12 right-4 w-12 p-4 hover:bg-opacity-100 hover:cursor-pointer"
/>
<img
src="static/icon/play.png"
id="animateButton"
class="absolute bg-white backdrop-blur-sm bg-opacity-60 rounded-xl shadow-lg bottom-28 right-4 w-12 p-4 hover:bg-opacity-100 hover:cursor-pointer"
/>
<script>
let INIT_VIEW_STATE = {
longitude: 98.1339,
latitude: 10.863,
zoom: 5.594,
pitch: 48.3549,
bearing: -17.579,
};
var viewState = INIT_VIEW_STATE;
const firm_pin = new deck.IconLayer({
id: "IconLayerFIRM",
data: "data/firm/location_homepro_do_2018-2024.json",
getColor: (d) => [Math.sqrt(d.exits), 140, 0],
getIcon: (d) => "marker",
getPosition: (d) => [d.lon, d.lat],
getSize: 24,
iconAtlas:
"https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.png",
iconMapping:
"https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.json",
pickable: false,
});
// LAYER
/*
const firm_loc = new deck.HexagonLayer({
id: "HexagonLayer",
data: "data/firm/homeprto_disaster_firm_location_forecast.json",
//extruded: true,
getPosition: (d) => [d.lon, d.lat],
getColorWeight: (d) => d.wind_2021,
getElevationWeight: (d) => d.wind_2021,
elevationScale: 10,
colorRange: [
[255, 255, 178, 200],
[254, 217, 118, 200],
[254, 178, 76, 200],
[253, 141, 60, 200],
[240, 59, 32, 200],
[189, 0, 38, 200],
],
colorScaleType: "quantile",
radius: 5000,
pickable: true,
elevationAggregation: "MEAN",
colorAggregation: "MEAN",
});*/
const province_boundary = new deck.GeoJsonLayer({
id: "GeoJsonLayer",
data: "data/common/province_admin_diva_sim.geojson",
pickable: false,
getLineColor: [0, 0, 0],
getLineWidth: 200,
getFillColor: [255, 255, 255, 0],
});
// Initialize Deck.GL
const deckInstance = new deck.DeckGL({
initialViewState: INIT_VIEW_STATE,
container: "map",
mapStyle:
"https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json",
controller: { doubleClickZoom: true, inertia: true },
onViewStateChange: (e) => {
viewState = e.viewState;
//console.log(viewState);
},
getTooltip,
layers: [province_boundary, firm_pin],
});
function getTooltip({ object }) {
return (
object && {
html: `<h2 class="text-black">Disaster Index: ${object.colorValue}</h2>`,
className: "rounded-lg shadow-lg",
style: {
backgroundColor: "#fff",
fontSize: "0.8em",
},
}
);
}
function rotateCameraRight() {
initialViewState = {
...viewState,
bearing: viewState.bearing - 20,
transitionDuration: 10000,
transitionInterpolator: new deck.LinearInterpolator(["bearing"]),
onTransitionEnd: rotateCameraLeft,
};
deckInstance.setProps({ initialViewState });
}
function rotateCameraLeft() {
initialViewState = {
...viewState,
bearing: viewState.bearing + 20,
transitionDuration: 10000,
transitionInterpolator: new deck.LinearInterpolator(["bearing"]),
onTransitionEnd: rotateCameraRight,
};
deckInstance.setProps({ initialViewState });
}
function resetCameraPosition() {
deckInstance.setProps({
initialViewState: {
...INIT_VIEW_STATE,
transitionInterpolator: new deck.FlyToInterpolator({ speed: 2 }),
transitionDuration: "auto",
},
});
}
async function updateMap() {
console.log("update Map");
const selectedBoxId = getSelectedBox();
//console.log('Currently Selected Box ID:', selectedBoxId);
if (selectedBoxId == "wind") {
console.log(" Do something to Wind");
deckInstance.setProps({
layers: [
province_boundary,
new deck.HexagonLayer({
id: "HexagonLayer",
data: "data/firm/homeprto_disaster_firm_location_forecast.json",
//extruded: true,
getPosition: (d) => [d.lon, d.lat],
getColorWeight: (d) => d.wind_2023,
getElevationWeight: (d) => d.wind_2023,
elevationScale: 10,
colorRange: [
[255, 255, 178, 200],
[254, 217, 118, 200],
[254, 178, 76, 200],
[253, 141, 60, 200],
[240, 59, 32, 200],
[189, 0, 38, 200],
],
colorScaleType: "quantile",
radius: 5000,
pickable: true,
elevationAggregation: "MEAN",
colorAggregation: "MEAN",
}),
firm_pin,
],
getTooltip,
});
} else if (selectedBoxId == "flood") {
console.log(" Do something to Flood");
deckInstance.setProps({
layers: [
province_boundary,
new deck.HexagonLayer({
id: "HexagonLayer",
data: "data/firm/homeprto_disaster_firm_location_forecast.json",
//extruded: true,
getPosition: (d) => [d.lon, d.lat],
getColorWeight: (d) => d.flood_2023,
getElevationWeight: (d) => d.flood_2023,
elevationScale: 10,
colorRange: [
[242, 240, 247, 200],
[218, 218, 235, 200],
[188, 189, 220, 200],
[158, 154, 200, 200],
[117, 107, 177, 200],
[84, 39, 143, 200],
,
],
colorScaleType: "quantile",
radius: 5000,
pickable: true,
elevationAggregation: "MEAN",
colorAggregation: "MEAN",
}),
firm_pin,
],
getTooltip,
});
} else if (selectedBoxId == "pm") {
console.log(" Do something to PM");
deckInstance.setProps({
layers: [
province_boundary,
new deck.HexagonLayer({
id: "HexagonLayer",
data: "data/firm/homeprto_disaster_firm_location_forecast.json",
//extruded: true,
getPosition: (d) => [d.lon, d.lat],
getColorWeight: (d) => d.pm_2023,
getElevationWeight: (d) => d.pm_2023,
elevationScale: 10,
colorRange: [
[247, 247, 247, 200],
[217, 217, 217, 200],
[189, 189, 189, 200],
[150, 150, 150, 200],
[99, 99, 99, 200],
[37, 37, 37, 200],
],
colorScaleType: "quantile",
radius: 5000,
pickable: true,
elevationAggregation: "MEAN",
colorAggregation: "MEAN",
}),
firm_pin,
],
getTooltip,
});
}
// refresh again after 60 seconds
setTimeout(updateMap, 60000);
}
const resetButton = document.querySelector("#resetViewButton");
resetButton.addEventListener("click", () => {
resetCameraPosition();
});
tippy("#resetViewButton", {
content: "Reset View",
placement: "left",
});
const animateButton = document.querySelector("#animateButton");
animateButton.addEventListener("click", () => {
rotateCameraLeft();
});
tippy("#animateButton", {
content: "Animate View",
placement: "left",
});
tippy("#goOverView", {
content: "FIRM Overview",
placement: "left",
});
tippy("#goLocation", {
content: "Location-Based",
placement: "left",
});
tippy("#goForecast", {
content: "Forecasting",
placement: "left",
});
const boxes = document.querySelectorAll(".box");
boxes.forEach((box) => {
box.addEventListener("click", function () {
// Remove 'selected' class from all boxes
boxes.forEach((b) =>
b.classList.remove("selected", "bg-sky-500", "text-white")
);
// Add 'selected' class to the clicked box
this.classList.add("selected", "bg-sky-500", "text-white");
updateMap();
});
});
function getSelectedBox() {
const selectedBox = document.querySelector(".box.selected");
if (selectedBox) {
return selectedBox.getAttribute("data-id"); // Return the selected box's data-id
}
return null;
}
</script>
<script>
// First Chart.js Configuration
</script>
</body>
</html>