|
2 | 2 | <htmllang="en">
|
3 | 3 | <head>
|
4 | 4 | <metacharset="utf-8">
|
5 |
| -<title>Pyscript/Panel DeckGL Demo</title> |
| 5 | +<metaname="apple-mobile-web-app-capable"content="yes"> |
| 6 | +<metaname="apple-mobile-web-app-status-bar-style"content="default"> |
| 7 | +<metaname="theme-color"content="#0072b5"> |
| 8 | +<metaname="name"content="Pyscript/Panel DeckGL Demo"> |
6 | 9 |
|
7 |
| -<linkrel="icon"href="https://unpkg.com/@holoviz/panel@0.13.0/dist/icons/favicon.ico"type=""> |
8 |
| -<metaname="name"content="PyScript/Panel KMeans Demo"> |
| 10 | +<title>Pyscript/Panel DeckGL Demo</title> |
9 | 11 |
|
10 | 12 | <linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"type="text/css"/>
|
11 | 13 | <linkrel="stylesheet"href="https://unpkg.com/@holoviz/panel@0.13.0/dist/css/widgets.css"type="text/css"/>
|
|
24 | 26 | <scripttype="text/javascript"src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
|
25 | 27 | <scripttype="text/javascript"src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
|
26 | 28 | <scripttype="text/javascript"src="https://unpkg.com/@holoviz/panel@0.13.0/dist/panel.js"></script>
|
27 |
| -<scripttype="text/javascript"> |
28 |
| -Bokeh.set_log_level("info"); |
29 |
| -</script> |
30 |
| - |
| 29 | + |
31 | 30 | <linkrel="stylesheet"href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
|
32 | 31 | <linkrel="stylesheet"href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/bootstraptemplate/bootstrap.css">
|
33 | 32 | <linkrel="stylesheet"href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/defaulttheme/default.css">
|
34 | 33 |
|
| 34 | +<scriptsrc="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script> |
| 35 | +<scriptsrc="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 |
| -<scriptsrc="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script> |
42 |
| -<scriptsrc="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script> |
43 |
| - |
44 | 41 | <linkrel="stylesheet"href="../build/pyscript.css"/>
|
45 | 42 | <scriptdefersrc="../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()))
|
|