diff --git a/docs/notebooks/138_draw_control.ipynb b/docs/notebooks/138_draw_control.ipynb
new file mode 100644
index 0000000000..64ecdd51cb
--- /dev/null
+++ b/docs/notebooks/138_draw_control.ipynb
@@ -0,0 +1,173 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "**Clip Earth Engine images interactively with the Draw Control**\n",
+ "\n",
+ "Uncomment the following line to install [geemap](https://geemap.org) if needed."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# %pip install -U geemap"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import ee\n",
+ "import geemap\n",
+ "import ipywidgets as widgets"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Add some Earth Engine data to the map, then you can use the draw control and a button widget to clip the Earth Engine data by the drawn polygons. \n",
+ "\n",
+ "The drawn geometries can be retrieved as either an ee.Geometry object (`m.user_roi`) or ee.FeatureCollection (`m._user_rois`)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "self = geemap.Map(center=[0, 9.31], zoom=3)\n",
+ "image = ee.Image('USGS/SRTMGL1_003')\n",
+ "vis_params = {\n",
+ " 'min': 0,\n",
+ " 'max': 6000,\n",
+ " 'palette': 'terrain',\n",
+ "}\n",
+ "self.add_layer(image, vis_params, 'SRTM')\n",
+ "\n",
+ "clip_btn = widgets.Button(description='Clip Image')\n",
+ "reset_btn = widgets.Button(description='Reset')\n",
+ "\n",
+ "def on_clip_btn_clicked(b):\n",
+ " if self.user_roi is not None:\n",
+ " try:\n",
+ " clipped_image = image.clip(self.user_roi)\n",
+ " self.add_layer(clipped_image, vis_params, 'Clipped Image')\n",
+ " self.find_layer('SRTM').visible = False\n",
+ " except:\n",
+ " pass\n",
+ "\n",
+ "clip_btn.on_click(on_clip_btn_clicked)\n",
+ "\n",
+ "def on_reset_btn_clicked(b):\n",
+ " self._draw_control.clear()\n",
+ " self.find_layer('SRTM').visible = True\n",
+ " self.layers = self.layers[:3]\n",
+ "\n",
+ "reset_btn.on_click(on_reset_btn_clicked)\n",
+ "\n",
+ "widget = widgets.VBox([clip_btn, reset_btn])\n",
+ "self.add_widget(widget, position='bottomright')\n",
+ "self"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Create a solara web app."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import ee\n",
+ "import geemap\n",
+ "import solara\n",
+ "import ipywidgets as widgets\n",
+ "\n",
+ "\n",
+ "class Map(geemap.Map):\n",
+ " def __init__(self, **kwargs):\n",
+ " super().__init__(**kwargs)\n",
+ "\n",
+ " image = ee.Image('USGS/SRTMGL1_003')\n",
+ " vis_params = {\n",
+ " 'min': 0,\n",
+ " 'max': 6000,\n",
+ " 'palette': 'terrain',\n",
+ " }\n",
+ " self.add_layer(image, vis_params, 'SRTM')\n",
+ "\n",
+ " clip_btn = widgets.Button(description='Clip Image')\n",
+ " reset_btn = widgets.Button(description='Reset')\n",
+ "\n",
+ " def on_clip_btn_clicked(b):\n",
+ " if self.user_roi is not None:\n",
+ " try:\n",
+ " clipped_image = image.clip(self.user_roi)\n",
+ " self.add_layer(clipped_image, vis_params, 'Clipped Image')\n",
+ " self.find_layer('SRTM').visible = False\n",
+ " except:\n",
+ " pass\n",
+ "\n",
+ " clip_btn.on_click(on_clip_btn_clicked)\n",
+ "\n",
+ " def on_reset_btn_clicked(b):\n",
+ " self._draw_control.clear()\n",
+ " self.find_layer('SRTM').visible = True\n",
+ " self.layers = self.layers[:3]\n",
+ "\n",
+ " reset_btn.on_click(on_reset_btn_clicked)\n",
+ "\n",
+ " widget = widgets.VBox([clip_btn, reset_btn])\n",
+ " self.add_widget(widget, position='bottomright')\n",
+ "\n",
+ "\n",
+ "@solara.component\n",
+ "def Page():\n",
+ " with solara.Column(style={\"min-width\": \"500px\"}):\n",
+ " Map.element(\n",
+ " center=[0, 9.31],\n",
+ " zoom=3,\n",
+ " height=\"600px\",\n",
+ " )\n",
+ "Page()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/docs/tutorials.md b/docs/tutorials.md
index 717a720001..2df77703c9 100644
--- a/docs/tutorials.md
+++ b/docs/tutorials.md
@@ -149,3 +149,4 @@ More video tutorials for geemap and Earth Engine are available on my [YouTube ch
135. Earth Engine Image Segmentation with the Segment Anything Model ([notebook](https://geemap.org/notebooks/135_segmentation))
136. Downloading Earth Engine images in parallel ([notebook](https://geemap.org/notebooks/136_download_parallel))
137. Creating a rectangular grid covering a region of interest for computing zonal statistics ([notebook](https://geemap.org/notebooks/137_create_grid))
+138. Clipping Earth Engine images interactively with the Draw Control ([notebook](https://geemap.org/notebooks/138_draw_control))
diff --git a/examples/README.md b/examples/README.md
index 9dcdce7885..ebcc1190dd 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -154,6 +154,7 @@ More video tutorials for geemap and Earth Engine are available on my [YouTube ch
135. Earth Engine Image Segmentation with the Segment Anything Model ([notebook](https://geemap.org/notebooks/135_segmentation))
136. Downloading Earth Engine images in parallel ([notebook](https://geemap.org/notebooks/136_download_parallel))
137. Creating a rectangular grid covering a region of interest for computing zonal statistics ([notebook](https://geemap.org/notebooks/137_create_grid))
+138. Clipping Earth Engine images interactively with the Draw Control ([notebook](https://geemap.org/notebooks/138_draw_control))
### 1. Introducing the geemap Python package for interactive mapping with Google Earth Engine
diff --git a/examples/notebooks/138_draw_control.ipynb b/examples/notebooks/138_draw_control.ipynb
new file mode 100644
index 0000000000..64ecdd51cb
--- /dev/null
+++ b/examples/notebooks/138_draw_control.ipynb
@@ -0,0 +1,173 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "**Clip Earth Engine images interactively with the Draw Control**\n",
+ "\n",
+ "Uncomment the following line to install [geemap](https://geemap.org) if needed."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# %pip install -U geemap"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import ee\n",
+ "import geemap\n",
+ "import ipywidgets as widgets"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Add some Earth Engine data to the map, then you can use the draw control and a button widget to clip the Earth Engine data by the drawn polygons. \n",
+ "\n",
+ "The drawn geometries can be retrieved as either an ee.Geometry object (`m.user_roi`) or ee.FeatureCollection (`m._user_rois`)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "self = geemap.Map(center=[0, 9.31], zoom=3)\n",
+ "image = ee.Image('USGS/SRTMGL1_003')\n",
+ "vis_params = {\n",
+ " 'min': 0,\n",
+ " 'max': 6000,\n",
+ " 'palette': 'terrain',\n",
+ "}\n",
+ "self.add_layer(image, vis_params, 'SRTM')\n",
+ "\n",
+ "clip_btn = widgets.Button(description='Clip Image')\n",
+ "reset_btn = widgets.Button(description='Reset')\n",
+ "\n",
+ "def on_clip_btn_clicked(b):\n",
+ " if self.user_roi is not None:\n",
+ " try:\n",
+ " clipped_image = image.clip(self.user_roi)\n",
+ " self.add_layer(clipped_image, vis_params, 'Clipped Image')\n",
+ " self.find_layer('SRTM').visible = False\n",
+ " except:\n",
+ " pass\n",
+ "\n",
+ "clip_btn.on_click(on_clip_btn_clicked)\n",
+ "\n",
+ "def on_reset_btn_clicked(b):\n",
+ " self._draw_control.clear()\n",
+ " self.find_layer('SRTM').visible = True\n",
+ " self.layers = self.layers[:3]\n",
+ "\n",
+ "reset_btn.on_click(on_reset_btn_clicked)\n",
+ "\n",
+ "widget = widgets.VBox([clip_btn, reset_btn])\n",
+ "self.add_widget(widget, position='bottomright')\n",
+ "self"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Create a solara web app."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import ee\n",
+ "import geemap\n",
+ "import solara\n",
+ "import ipywidgets as widgets\n",
+ "\n",
+ "\n",
+ "class Map(geemap.Map):\n",
+ " def __init__(self, **kwargs):\n",
+ " super().__init__(**kwargs)\n",
+ "\n",
+ " image = ee.Image('USGS/SRTMGL1_003')\n",
+ " vis_params = {\n",
+ " 'min': 0,\n",
+ " 'max': 6000,\n",
+ " 'palette': 'terrain',\n",
+ " }\n",
+ " self.add_layer(image, vis_params, 'SRTM')\n",
+ "\n",
+ " clip_btn = widgets.Button(description='Clip Image')\n",
+ " reset_btn = widgets.Button(description='Reset')\n",
+ "\n",
+ " def on_clip_btn_clicked(b):\n",
+ " if self.user_roi is not None:\n",
+ " try:\n",
+ " clipped_image = image.clip(self.user_roi)\n",
+ " self.add_layer(clipped_image, vis_params, 'Clipped Image')\n",
+ " self.find_layer('SRTM').visible = False\n",
+ " except:\n",
+ " pass\n",
+ "\n",
+ " clip_btn.on_click(on_clip_btn_clicked)\n",
+ "\n",
+ " def on_reset_btn_clicked(b):\n",
+ " self._draw_control.clear()\n",
+ " self.find_layer('SRTM').visible = True\n",
+ " self.layers = self.layers[:3]\n",
+ "\n",
+ " reset_btn.on_click(on_reset_btn_clicked)\n",
+ "\n",
+ " widget = widgets.VBox([clip_btn, reset_btn])\n",
+ " self.add_widget(widget, position='bottomright')\n",
+ "\n",
+ "\n",
+ "@solara.component\n",
+ "def Page():\n",
+ " with solara.Column(style={\"min-width\": \"500px\"}):\n",
+ " Map.element(\n",
+ " center=[0, 9.31],\n",
+ " zoom=3,\n",
+ " height=\"600px\",\n",
+ " )\n",
+ "Page()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}