Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import streamlit.components.v1 as components | |
| import pandas as pd | |
| import json | |
| st.set_page_config(layout="wide") | |
| st.title("🧲 CesiumJS Footfall Drag-Drop Demo") | |
| # Load footfall data | |
| df = pd.read_excel("data/jj_with_footfall.xlsx").dropna(subset=["latitude", "longitude"]) | |
| features = [ | |
| { | |
| "type": "Feature", | |
| "geometry": { | |
| "type": "Point", | |
| "coordinates": [row["longitude"], row["latitude"]], | |
| } | |
| } | |
| for _, row in df.iterrows() | |
| ] | |
| geojson_str = json.dumps({"type": "FeatureCollection", "features": features}) | |
| html_code = f""" | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <title>Cesium Draggable Footfall</title> | |
| <script src="https://cesium.com/downloads/cesiumjs/releases/1.104/Build/Cesium/Cesium.js"></script> | |
| <link href="https://cesium.com/downloads/cesiumjs/releases/1.104/Build/Cesium/Widgets/widgets.css" rel="stylesheet"> | |
| <style> | |
| html, body, #cesiumContainer {{ | |
| width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; | |
| }} | |
| </style> | |
| </head> | |
| <body> | |
| <div id="cesiumContainer"></div> | |
| <script> | |
| Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0M2VmOTcyMi0wZDIyLTRjMjktOTNlNi0zNjg2MmQyNTFjYTQiLCJpZCI6Mjk3Njk1LCJpYXQiOjE3NDU3NzgyMzh9.0FuHB-PidaNCTRT1sdcp20ufMJ5Z8DEEArhr47BOo4A'; | |
| const viewer = new Cesium.Viewer('cesiumContainer', {{ | |
| terrainProvider: Cesium.createWorldTerrain(), | |
| selectionIndicator: false | |
| }}); | |
| const data = {geojson_str}; | |
| const markers = []; | |
| let pickedEntity = null; | |
| const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); | |
| data.features.forEach((feature, i) => {{ | |
| const [lon, lat] = feature.geometry.coordinates; | |
| const entity = viewer.entities.add({{ | |
| id: "point_" + i, | |
| position: Cesium.Cartesian3.fromDegrees(lon, lat), | |
| billboard: {{ | |
| image: 'https://cdn-icons-png.flaticon.com/512/684/684908.png', | |
| width: 24, | |
| height: 24 | |
| }} | |
| }}); | |
| markers.push(entity); | |
| }}); | |
| viewer.zoomTo(viewer.entities); | |
| // Drag logic | |
| handler.setInputAction((click) => {{ | |
| const picked = viewer.scene.pick(click.position); | |
| if (Cesium.defined(picked) && picked.id) {{ | |
| pickedEntity = picked.id; | |
| viewer.scene.screenSpaceCameraController.enableRotate = false; | |
| }} | |
| }}, Cesium.ScreenSpaceEventType.LEFT_DOWN); | |
| handler.setInputAction((movement) => {{ | |
| if (pickedEntity) {{ | |
| const cartesian = viewer.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid); | |
| if (cartesian) {{ | |
| pickedEntity.position = cartesian; | |
| }} | |
| }} | |
| }}, Cesium.ScreenSpaceEventType.MOUSE_MOVE); | |
| handler.setInputAction(() => {{ | |
| pickedEntity = null; | |
| viewer.scene.screenSpaceCameraController.enableRotate = true; | |
| }}, Cesium.ScreenSpaceEventType.LEFT_UP); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| components.html(html_code, height=700) | |