|
2 | 2 | <html lang="en">
|
3 | 3 | <head>
|
4 | 4 | <meta charset="utf-8">
|
5 |
| - <title>Pyscript/Panel DeckGL Demo</title> |
| 5 | + <meta name="apple-mobile-web-app-capable" content="yes"> |
| 6 | + <meta name="apple-mobile-web-app-status-bar-style" content="default"> |
| 7 | + <meta name="theme-color" content="#0072b5"> |
| 8 | + <meta name="name" content="Pyscript/Panel DeckGL Demo"> |
6 | 9 |
|
7 |
| - <link rel="icon" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/icons/favicon.ico" type=""> |
8 |
| - <meta name="name" content="PyScript/Panel KMeans Demo"> |
| 10 | + <title>Pyscript/Panel DeckGL Demo</title> |
9 | 11 |
|
10 | 12 | <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" type="text/css" />
|
11 | 13 | <link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/css/widgets.css" type="text/css" />
|
|
24 | 26 | <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
|
25 | 27 | <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
|
26 | 28 | <script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.0/dist/panel.js"></script>
|
27 |
| - <script type="text/javascript"> |
28 |
| - Bokeh.set_log_level("info"); |
29 |
| - </script> |
30 |
| - |
| 29 | + |
31 | 30 | <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
|
32 | 31 | <link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/bootstraptemplate/bootstrap.css">
|
33 | 32 | <link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/defaulttheme/default.css">
|
34 | 33 |
|
| 34 | + <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script> |
| 35 | + <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script> |
35 | 36 | <style>
|
36 | 37 | #sidebar {
|
37 |
| - width: 350px; |
| 38 | + width: 400px; |
38 | 39 | }
|
39 | 40 | </style>
|
40 |
| - |
41 |
| - <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script> |
42 |
| - <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script> |
43 |
| - |
44 | 41 | <link rel="stylesheet" href="../build/pyscript.css" />
|
45 | 42 | <script defer src="../build/pyscript.js"></script>
|
46 | 43 | </head>
|
|
98 | 95 |
|
99 | 96 | view = param.DataFrame(precedence=-1)
|
100 | 97 |
|
| 98 | + arc_view = param.DataFrame(precedence=-1) |
| 99 | + |
101 | 100 | radius = param.Integer(default=50, bounds=(20, 1000))
|
102 | 101 |
|
103 | 102 | elevation = param.Integer(default=10, bounds=(0, 50))
|
|
111 | 110 | def __init__(self, **params):
|
112 | 111 | self.deck_gl = None
|
113 | 112 | super().__init__(**params)
|
114 |
| - self.deck_gl = pn.pane.DeckGL(dict(self.spec), mapbox_api_key=MAPBOX_KEY, sizing_mode='stretch_both', margin=0) |
115 |
| - self.deck_gl.param.watch(self.update_spec, 'hover_state') |
| 113 | + self.deck_gl = pn.pane.DeckGL( |
| 114 | + dict(self.spec), mapbox_api_key=MAPBOX_KEY, throttle={'click': 10}, |
| 115 | + sizing_mode='stretch_both', margin=0) |
| 116 | + self.deck_gl.param.watch(self._update_arc_view, 'click_state') |
116 | 117 | self._playing = False
|
117 |
| - self._cb = pn.state.add_periodic_callback(self._update, 1000//self.speed, start=False) |
| 118 | + self._cb = pn.state.add_periodic_callback( |
| 119 | + self._update_hour, 1000//self.speed, start=False |
| 120 | + ) |
118 | 121 |
|
119 |
| - @param.depends('speed', watch=True) |
120 |
| - def _update_speed(self): |
121 |
| - self._cb.period = 1000//self.speed |
| 122 | + def __panel__(self): |
| 123 | + return self.deck_gl |
122 | 124 |
|
123 | 125 | @property
|
124 | 126 | def spec(self):
|
|
168 | 170 | "getTargetColor": [240, 100, 0, 180]
|
169 | 171 | }
|
170 | 172 |
|
171 |
| - @property |
172 |
| - def arc_view(self): |
173 |
| - data = self.data if self.view is None else self.view |
174 |
| - if not self.deck_gl or not self.deck_gl.hover_state: |
175 |
| - return data.iloc[:0] |
176 |
| - lon, lat = self.deck_gl.hover_state['coordinate'] |
177 |
| - tol = 0.001 |
178 |
| - return data[ |
179 |
| - (df.pickup_x>=float(lon-tol)) & |
180 |
| - (df.pickup_x<=float(lon+tol)) & |
181 |
| - (df.pickup_y>=float(lat-tol)) & |
182 |
| - (df.pickup_y<=float(lat+tol)) |
183 |
| - ] |
184 |
| - |
185 |
| - def _update(self): |
| 173 | + def _update_hour(self): |
186 | 174 | self.hour = (self.hour+1) % 24
|
| 175 | + |
| 176 | + @param.depends('view', watch=True) |
| 177 | + def _update_arc_view(self, event=None): |
| 178 | + data = self.data if self.view is None else self.view |
| 179 | + if not self.deck_gl or not self.deck_gl.click_state: |
| 180 | + self.arc_view = data.iloc[:0] |
| 181 | + else: |
| 182 | + lon, lat = self.deck_gl.click_state['coordinate'] |
| 183 | + tol = 0.001 |
| 184 | + self.arc_view = data[ |
| 185 | + (df.pickup_x>=float(lon-tol)) & |
| 186 | + (df.pickup_x<=float(lon+tol)) & |
| 187 | + (df.pickup_y>=float(lat-tol)) & |
| 188 | + (df.pickup_y<=float(lat+tol)) |
| 189 | + ] |
| 190 | + |
| 191 | + @param.depends('hour', watch=True) |
| 192 | + def _update_hourly_view(self): |
187 | 193 | self.view = self.data[self.data.hour==self.hour]
|
188 | 194 |
|
| 195 | + @param.depends('speed', watch=True) |
| 196 | + def _update_speed(self): |
| 197 | + self._cb.period = 1000//self.speed |
| 198 | + |
189 | 199 | @param.depends('play', watch=True)
|
190 | 200 | def _play_pause(self):
|
191 | 201 | if self._playing:
|
|
198 | 208 | self.param.speed.precedence = 1
|
199 | 209 | self._playing = not self._playing
|
200 | 210 |
|
201 |
| - @param.depends('view', 'radius', 'elevation', watch=True) |
202 |
| - def update_spec(self, *events): |
| 211 | + @param.depends('view', 'radius', 'elevation', 'arc_view', watch=True) |
| 212 | + def update_spec(self): |
203 | 213 | self.deck_gl.object = dict(self.spec)
|
204 | 214 |
|
205 |
| - def __panel__(self): |
206 |
| - return self.deck_gl |
207 | 215 |
|
208 | 216 | data = await fetch('https://s3.eu-west-1.amazonaws.com/assets.holoviews.org/data/nyc_taxi_wide.csv')
|
209 | 217 | df = pd.read_csv(StringIO(await data.text()))
|
|
0 commit comments