{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Demonstrates loading deck.gl as external JSS and CSS components, rendering it as part of an app, and then linking it to Panel widgets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "\n",
    "js_files = {'deck': 'https://cdn.jsdelivr.net/npm/deck.gl@8.1.12/dist.min.js',\n",
    "            'mapboxgl': 'https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.js'}\n",
    "css_files = ['https://api.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.css']\n",
    "\n",
    "pn.extension(js_files=js_files, css_files=css_files, sizing_mode=\"stretch_width\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, let's declare the cities we are interested in using Python:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cities = [\n",
    "    {\"city\":\"San Francisco\",\"state\":\"California\",\"latitude\":37.7751,\"longitude\":-122.4193},\n",
    "    {\"city\":\"New York\",\"state\":\"New York\",\"latitude\":40.6643,\"longitude\":-73.9385},\n",
    "    {\"city\":\"Los Angeles\",\"state\":\"California\",\"latitude\":34.051597,\"longitude\":-118.244263},\n",
    "    {\"city\":\"London\",\"state\":\"United Kingdom\",\"latitude\":51.5074,\"longitude\":-0.1278},\n",
    "    {\"city\":\"Hyderabad\",\"state\":\"India\",\"latitude\":17.3850,\"longitude\":78.4867}]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, let's declare an HTML `<div>` to render the plot into, then define the deck.gl script code to render a plot for those cities."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "html = \"\"\"\n",
    "<div id=\"deckgl-container\" style=\"height: 500px;width: 100p\"></div>\n",
    "\n",
    "<script type=\"text/javascript\">\n",
    "// Data\n",
    "var CITIES = %s;\n",
    "var deckgl = new deck.DeckGL({\n",
    "  container: 'deckgl-container',\n",
    "  mapboxApiAccessToken: 'pk.eyJ1IjoicGhpbGlwcGpmciIsImEiOiJjajM2bnE4MWcwMDNxMzNvMHMzcGV3NjlnIn0.976fZ1azCrTh50lEdZTpSg',\n",
    "  initialViewState: {\n",
    "      longitude: CITIES[0].longitude,\n",
    "      latitude: CITIES[0].latitude,\n",
    "      zoom: 10,\n",
    "  },\n",
    "  controller: true,\n",
    "  layers: [\n",
    "    new deck.ScatterplotLayer({\n",
    "      data: CITIES,\n",
    "      getPosition: d => [d.longitude, d.latitude],\n",
    "      radiusMinPixels: 10\n",
    "    })\n",
    "  ],\n",
    "});\n",
    "</script>\n",
    "\"\"\" % cities\n",
    "deckgl = pn.pane.HTML(html, height=500)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we can declare a Panel widget and define a ``jslink`` to update the deck.gl plot whenever the widget state changes. The example is adapted from https://deck.gl/gallery/viewport-transition but replaces D3 widgets with Panel-based widgets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "widget = pn.widgets.RadioButtonGroup(options=[c[\"city\"] for c in cities])\n",
    "\n",
    "update_city = \"\"\"\n",
    "var d = CITIES[source.active];\n",
    "deckgl.setProps({\n",
    "    initialViewState: {\n",
    "        longitude: d.longitude,\n",
    "        latitude: d.latitude,\n",
    "        zoom: 10,\n",
    "        transitionInterpolator: new deck.FlyToInterpolator({speed: 1.5}),\n",
    "        transitionDuration: 'auto'\n",
    "      }\n",
    "});\n",
    "\"\"\"\n",
    "\n",
    "widget.jslink(deckgl, code={'active': update_city});\n",
    "\n",
    "component = pn.Column(widget, deckgl)\n",
    "component"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## App\n",
    "\n",
    "Lets wrap it into nice template that can be served via `panel serve deckgl.ipynb`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pn.template.FastListTemplate(site=\"Panel\", title=\"Deck.gl\", main=[\"This app **demonstrates loading deck.gl JSS and CSS components** and then linking it to Panel widgets.\", component]).servable();"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
