File size: 2,938 Bytes
88825fa
51d6e55
7130008
08c6b8e
7130008
2b52006
d2abd81
08c6b8e
2b31433
be78d85
2b31433
 
08c6b8e
 
 
2b31433
d2abd81
2b31433
 
 
51d6e55
2b31433
08c6b8e
7130008
51d6e55
 
2059ee0
2b31433
 
 
 
 
 
 
 
 
2059ee0
 
 
 
2b31433
 
 
 
 
 
 
 
 
 
17785c0
2b31433
 
 
d2abd81
2b31433
 
 
 
 
 
7130008
2b31433
 
17785c0
2b31433
51d6e55
2b31433
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51d6e55
2b31433
 
 
 
2059ee0
 
51d6e55
 
 
2059ee0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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)