streamlit-drawable-canvas-jsretry


Namestreamlit-drawable-canvas-jsretry JSON
Version 0.9.3 PyPI version JSON
download
home_pagehttps://github.com/andfanilo/streamlit-drawable-canvas
SummaryA Streamlit custom component for a free drawing canvas using Fabric.js. A fork to enable retrying for bg images.
upload_time2023-12-21 19:18:00
maintainer
docs_urlNone
authorVik Paruchuri
requires_python>=3.6
license
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Streamlit - Drawable Canvas

Streamlit component which provides a sketching canvas using [Fabric.js](http://fabricjs.com/).

[![Streamlit App](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://share.streamlit.io/andfanilo/streamlit-drawable-canvas-demo/master/app.py)

[![PyPI](https://img.shields.io/pypi/v/streamlit-drawable-canvas)](https://pypi.org/project/streamlit-drawable-canvas/)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/streamlit-drawable-canvas)](https://pypi.org/project/streamlit-drawable-canvas/)

<a href="https://www.buymeacoffee.com/andfanilo" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="50" width="180"></a>

![](./img/demo.gif)

## Features

- Draw freely, lines, circles, boxes and polygons on the canvas, with options on stroke & fill
- Rotate, skew, scale, move any object of the canvas on demand
- Select a background color or image to draw on
- Get image data and every drawn object properties back to Streamlit !
- Choose to fetch back data in realtime or on demand with a button
- Undo, Redo or Delete canvas contents
- Save canvas data as JSON to reuse for another session

## Installation

```shell script
pip install streamlit-drawable-canvas
```

## Example Usage

Copy this code snippet:

```python
import pandas as pd
from PIL import Image
import streamlit as st
from streamlit_drawable_canvas import st_canvas

# Specify canvas parameters in application
drawing_mode = st.sidebar.selectbox(
    "Drawing tool:", ("point", "freedraw", "line", "rect", "circle", "transform")
)

stroke_width = st.sidebar.slider("Stroke width: ", 1, 25, 3)
if drawing_mode == 'point':
    point_display_radius = st.sidebar.slider("Point display radius: ", 1, 25, 3)
stroke_color = st.sidebar.color_picker("Stroke color hex: ")
bg_color = st.sidebar.color_picker("Background color hex: ", "#eee")
bg_image = st.sidebar.file_uploader("Background image:", type=["png", "jpg"])

realtime_update = st.sidebar.checkbox("Update in realtime", True)

    

# Create a canvas component
canvas_result = st_canvas(
    fill_color="rgba(255, 165, 0, 0.3)",  # Fixed fill color with some opacity
    stroke_width=stroke_width,
    stroke_color=stroke_color,
    background_color=bg_color,
    background_image=Image.open(bg_image) if bg_image else None,
    update_streamlit=realtime_update,
    height=150,
    drawing_mode=drawing_mode,
    point_display_radius=point_display_radius if drawing_mode == 'point' else 0,
    key="canvas",
)

# Do something interesting with the image data and paths
if canvas_result.image_data is not None:
    st.image(canvas_result.image_data)
if canvas_result.json_data is not None:
    objects = pd.json_normalize(canvas_result.json_data["objects"]) # need to convert obj to str because PyArrow
    for col in objects.select_dtypes(include=['object']).columns:
        objects[col] = objects[col].astype("str")
    st.dataframe(objects)
```

You will find more detailed examples [on the demo app](https://github.com/andfanilo/streamlit-drawable-canvas-demo/).

## API

```
st_canvas(
    fill_color: str
    stroke_width: int
    stroke_color: str
    background_color: str
    background_image: Image
    update_streamlit: bool
    height: int
    width: int
    drawing_mode: str
    initial_drawing: dict
    display_toolbar: bool
    point_display_radius: int
    key: str
)
```

- **fill_color** : Color of fill for Rect in CSS color property. Defaults to "#eee".
- **stroke_width** : Width of drawing brush in CSS color property. Defaults to 20.
- **stroke_color** : Color of drawing brush in hex. Defaults to "black".
- **background_color** : Color of canvas background in CSS color property. Defaults to "" which is transparent. Overriden by background_image. Changing background_color will reset the drawing.
- **background_image** : Pillow Image to display behind canvas. Automatically resized to canvas dimensions. Being behind the canvas, it is not sent back to Streamlit on mouse event. Overrides background_color. Changes to this will reset canvas contents.
- **update_streamlit** : Whenever True, send canvas data to Streamlit when object/selection is updated or mouse up.
- **height** : Height of canvas in pixels. Defaults to 400.
- **width** : Width of canvas in pixels. Defaults to 600.
- **drawing_mode** : Enable free drawing when "freedraw", object manipulation when "transform", otherwise create new objects with "line", "rect", "circle" and "polygon". Defaults to "freedraw".
  - On "polygon" mode, double-clicking will remove the latest point and right-clicking will close the polygon.
- **initial_drawing** : Initialize canvas with drawings from here. Should be the `json_data` output from other canvas. Beware: if you try to import a drawing from a bigger/smaller canvas, no rescaling is done in the canvas and the import could fail.
- **point_display_radius** : To make points visible on the canvas, they are drawn as circles. This parameter modifies the radius of the displayed circle.
- **display_toolbar** : If `False`, don't display the undo/redo/delete toolbar.

Example:

```python
import streamlit as st
from streamlit_drawable_canvas import st_canvas

canvas_result = st_canvas()
st_canvas(initial_drawing=canvas_result.json_data)
```

- **display_toolbar** : Display the undo/redo/reset toolbar.
- **key** : An optional string to use as the unique key for the widget. Assign a key so the component is not remount every time the script is rerun.

## Development

### Install

- JS side

```shell script
cd frontend
npm install
```

- Python side

```shell script
conda create -n streamlit-drawable-canvas python=3.7
conda activate streamlit-drawable-canvas
pip install -e .
```

### Run

Both webpack dev server and Streamlit should run at the same time.

- JS side

```shell script
cd frontend
npm run start
```

- Python side

```shell script
streamlit run app.py
```

### Cypress integration tests

- Install Cypress: `cd e2e; npm i` or `npx install cypress` (with `--force` if cache problem)
- Start Streamlit frontend server: `cd streamlit_drawable_canvas/frontend; npm run start`
- Start Streamlit test script: `streamlit run e2e/app_to_test.py`
- Start Cypress app: `cd e2e; npm run cypress:open`

## References

- [react-sketch](https://github.com/tbolis/react-sketch)
- [React hooks - fabric](https://github.com/fabricjs/fabric.js/issues/5951#issuecomment-563427231)
- [Simulate Retina display](https://stackoverflow.com/questions/12243549/how-to-test-a-webpage-meant-for-retina-display)
- [High DPI Canvas](https://www.html5rocks.com/en/tutorials/canvas/hidpi/)
- [Drawing with FabricJS and TypeScript Part 2: Straight Lines](https://exceptionnotfound.net/drawing-with-fabricjs-and-typescript-part-2-straight-lines/)
- [Drawing with FabricJS and TypeScript Part 7: Undo/Redo](https://exceptionnotfound.net/drawing-with-fabricjs-and-typescript-part-7-undo-redo/)
- [Types for classes as values in TypeScript](https://2ality.com/2020/04/classes-as-values-typescript.html)
- [Working with iframes in Cypress](https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/)
- [How to use useReducer in React Hooks for performance optimization](https://medium.com/crowdbotics/how-to-use-usereducer-in-react-hooks-for-performance-optimization-ecafca9e7bf5)
- [Understanding React Default Props](https://blog.bitsrc.io/understanding-react-default-props-5c50401ed37d)
- [How to avoid passing callbacks down?](https://reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down)
- [Examples of the useReducer Hook](https://daveceddia.com/usereducer-hook-examples/) The `useRef` hook allows you to create a persistent ref to a DOM node, or really to any value. React will persist this value between re-renders (between calls to your component function).
- [CSS filter generator to convert from black to target hex color](https://codepen.io/sosuke/pen/Pjoqqp)
- [When does React re-render components?](https://felixgerschau.com/react-rerender-components/#when-does-react-re-render)
- [Immutable Update Patterns](https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns)
- Icons by [Freepik](https://www.flaticon.com/authors/freepik), [Google](https://www.flaticon.com/authors/google), [Mavadee](https://www.flaticon.com/authors/mavadee).

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/andfanilo/streamlit-drawable-canvas",
    "name": "streamlit-drawable-canvas-jsretry",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "",
    "author": "Vik Paruchuri",
    "author_email": "github@vikas.sh",
    "download_url": "https://files.pythonhosted.org/packages/73/04/9ce6eca67cbe0f449e475bee91098e90e1a42083db3295023736b19e54f9/streamlit-drawable-canvas-jsretry-0.9.3.tar.gz",
    "platform": null,
    "description": "# Streamlit - Drawable Canvas\n\nStreamlit component which provides a sketching canvas using [Fabric.js](http://fabricjs.com/).\n\n[![Streamlit App](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://share.streamlit.io/andfanilo/streamlit-drawable-canvas-demo/master/app.py)\n\n[![PyPI](https://img.shields.io/pypi/v/streamlit-drawable-canvas)](https://pypi.org/project/streamlit-drawable-canvas/)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/streamlit-drawable-canvas)](https://pypi.org/project/streamlit-drawable-canvas/)\n\n<a href=\"https://www.buymeacoffee.com/andfanilo\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" height=\"50\" width=\"180\"></a>\n\n![](./img/demo.gif)\n\n## Features\n\n- Draw freely, lines, circles, boxes and polygons on the canvas, with options on stroke & fill\n- Rotate, skew, scale, move any object of the canvas on demand\n- Select a background color or image to draw on\n- Get image data and every drawn object properties back to Streamlit !\n- Choose to fetch back data in realtime or on demand with a button\n- Undo, Redo or Delete canvas contents\n- Save canvas data as JSON to reuse for another session\n\n## Installation\n\n```shell script\npip install streamlit-drawable-canvas\n```\n\n## Example Usage\n\nCopy this code snippet:\n\n```python\nimport pandas as pd\nfrom PIL import Image\nimport streamlit as st\nfrom streamlit_drawable_canvas import st_canvas\n\n# Specify canvas parameters in application\ndrawing_mode = st.sidebar.selectbox(\n    \"Drawing tool:\", (\"point\", \"freedraw\", \"line\", \"rect\", \"circle\", \"transform\")\n)\n\nstroke_width = st.sidebar.slider(\"Stroke width: \", 1, 25, 3)\nif drawing_mode == 'point':\n    point_display_radius = st.sidebar.slider(\"Point display radius: \", 1, 25, 3)\nstroke_color = st.sidebar.color_picker(\"Stroke color hex: \")\nbg_color = st.sidebar.color_picker(\"Background color hex: \", \"#eee\")\nbg_image = st.sidebar.file_uploader(\"Background image:\", type=[\"png\", \"jpg\"])\n\nrealtime_update = st.sidebar.checkbox(\"Update in realtime\", True)\n\n    \n\n# Create a canvas component\ncanvas_result = st_canvas(\n    fill_color=\"rgba(255, 165, 0, 0.3)\",  # Fixed fill color with some opacity\n    stroke_width=stroke_width,\n    stroke_color=stroke_color,\n    background_color=bg_color,\n    background_image=Image.open(bg_image) if bg_image else None,\n    update_streamlit=realtime_update,\n    height=150,\n    drawing_mode=drawing_mode,\n    point_display_radius=point_display_radius if drawing_mode == 'point' else 0,\n    key=\"canvas\",\n)\n\n# Do something interesting with the image data and paths\nif canvas_result.image_data is not None:\n    st.image(canvas_result.image_data)\nif canvas_result.json_data is not None:\n    objects = pd.json_normalize(canvas_result.json_data[\"objects\"]) # need to convert obj to str because PyArrow\n    for col in objects.select_dtypes(include=['object']).columns:\n        objects[col] = objects[col].astype(\"str\")\n    st.dataframe(objects)\n```\n\nYou will find more detailed examples [on the demo app](https://github.com/andfanilo/streamlit-drawable-canvas-demo/).\n\n## API\n\n```\nst_canvas(\n    fill_color: str\n    stroke_width: int\n    stroke_color: str\n    background_color: str\n    background_image: Image\n    update_streamlit: bool\n    height: int\n    width: int\n    drawing_mode: str\n    initial_drawing: dict\n    display_toolbar: bool\n    point_display_radius: int\n    key: str\n)\n```\n\n- **fill_color** : Color of fill for Rect in CSS color property. Defaults to \"#eee\".\n- **stroke_width** : Width of drawing brush in CSS color property. Defaults to 20.\n- **stroke_color** : Color of drawing brush in hex. Defaults to \"black\".\n- **background_color** : Color of canvas background in CSS color property. Defaults to \"\" which is transparent. Overriden by background_image. Changing background_color will reset the drawing.\n- **background_image** : Pillow Image to display behind canvas. Automatically resized to canvas dimensions. Being behind the canvas, it is not sent back to Streamlit on mouse event. Overrides background_color. Changes to this will reset canvas contents.\n- **update_streamlit** : Whenever True, send canvas data to Streamlit when object/selection is updated or mouse up.\n- **height** : Height of canvas in pixels. Defaults to 400.\n- **width** : Width of canvas in pixels. Defaults to 600.\n- **drawing_mode** : Enable free drawing when \"freedraw\", object manipulation when \"transform\", otherwise create new objects with \"line\", \"rect\", \"circle\" and \"polygon\". Defaults to \"freedraw\".\n  - On \"polygon\" mode, double-clicking will remove the latest point and right-clicking will close the polygon.\n- **initial_drawing** : Initialize canvas with drawings from here. Should be the `json_data` output from other canvas. Beware: if you try to import a drawing from a bigger/smaller canvas, no rescaling is done in the canvas and the import could fail.\n- **point_display_radius** : To make points visible on the canvas, they are drawn as circles. This parameter modifies the radius of the displayed circle.\n- **display_toolbar** : If `False`, don't display the undo/redo/delete toolbar.\n\nExample:\n\n```python\nimport streamlit as st\nfrom streamlit_drawable_canvas import st_canvas\n\ncanvas_result = st_canvas()\nst_canvas(initial_drawing=canvas_result.json_data)\n```\n\n- **display_toolbar** : Display the undo/redo/reset toolbar.\n- **key** : An optional string to use as the unique key for the widget. Assign a key so the component is not remount every time the script is rerun.\n\n## Development\n\n### Install\n\n- JS side\n\n```shell script\ncd frontend\nnpm install\n```\n\n- Python side\n\n```shell script\nconda create -n streamlit-drawable-canvas python=3.7\nconda activate streamlit-drawable-canvas\npip install -e .\n```\n\n### Run\n\nBoth webpack dev server and Streamlit should run at the same time.\n\n- JS side\n\n```shell script\ncd frontend\nnpm run start\n```\n\n- Python side\n\n```shell script\nstreamlit run app.py\n```\n\n### Cypress integration tests\n\n- Install Cypress: `cd e2e; npm i` or `npx install cypress` (with `--force` if cache problem)\n- Start Streamlit frontend server: `cd streamlit_drawable_canvas/frontend; npm run start`\n- Start Streamlit test script: `streamlit run e2e/app_to_test.py`\n- Start Cypress app: `cd e2e; npm run cypress:open`\n\n## References\n\n- [react-sketch](https://github.com/tbolis/react-sketch)\n- [React hooks - fabric](https://github.com/fabricjs/fabric.js/issues/5951#issuecomment-563427231)\n- [Simulate Retina display](https://stackoverflow.com/questions/12243549/how-to-test-a-webpage-meant-for-retina-display)\n- [High DPI Canvas](https://www.html5rocks.com/en/tutorials/canvas/hidpi/)\n- [Drawing with FabricJS and TypeScript Part 2: Straight Lines](https://exceptionnotfound.net/drawing-with-fabricjs-and-typescript-part-2-straight-lines/)\n- [Drawing with FabricJS and TypeScript Part 7: Undo/Redo](https://exceptionnotfound.net/drawing-with-fabricjs-and-typescript-part-7-undo-redo/)\n- [Types for classes as values in TypeScript](https://2ality.com/2020/04/classes-as-values-typescript.html)\n- [Working with iframes in Cypress](https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/)\n- [How to use useReducer in React Hooks for performance optimization](https://medium.com/crowdbotics/how-to-use-usereducer-in-react-hooks-for-performance-optimization-ecafca9e7bf5)\n- [Understanding React Default Props](https://blog.bitsrc.io/understanding-react-default-props-5c50401ed37d)\n- [How to avoid passing callbacks down?](https://reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down)\n- [Examples of the useReducer Hook](https://daveceddia.com/usereducer-hook-examples/) The `useRef` hook allows you to create a persistent ref to a DOM node, or really to any value. React will persist this value between re-renders (between calls to your component function).\n- [CSS filter generator to convert from black to target hex color](https://codepen.io/sosuke/pen/Pjoqqp)\n- [When does React re-render components?](https://felixgerschau.com/react-rerender-components/#when-does-react-re-render)\n- [Immutable Update Patterns](https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns)\n- Icons by [Freepik](https://www.flaticon.com/authors/freepik), [Google](https://www.flaticon.com/authors/google), [Mavadee](https://www.flaticon.com/authors/mavadee).\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "A Streamlit custom component for a free drawing canvas using Fabric.js.  A fork to enable retrying for bg images.",
    "version": "0.9.3",
    "project_urls": {
        "Homepage": "https://github.com/andfanilo/streamlit-drawable-canvas"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0c416941234c27e06d5ffb2cdc75b630418528674634d04a0d20562312cfc224",
                "md5": "6f240b1e185dfe036665990b5458cb77",
                "sha256": "e8035daa0297b504cc184e58ddf15cfd59680241ce1c2d0d554de507a263ca20"
            },
            "downloads": -1,
            "filename": "streamlit_drawable_canvas_jsretry-0.9.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "6f240b1e185dfe036665990b5458cb77",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 1169628,
            "upload_time": "2023-12-21T19:17:58",
            "upload_time_iso_8601": "2023-12-21T19:17:58.111481Z",
            "url": "https://files.pythonhosted.org/packages/0c/41/6941234c27e06d5ffb2cdc75b630418528674634d04a0d20562312cfc224/streamlit_drawable_canvas_jsretry-0.9.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "73049ce6eca67cbe0f449e475bee91098e90e1a42083db3295023736b19e54f9",
                "md5": "50783274085cf66b35bd69c7f131a473",
                "sha256": "d9da8a863faeeae01c8521e8e282ed83cc15b845962519149a61fc8eead7afe6"
            },
            "downloads": -1,
            "filename": "streamlit-drawable-canvas-jsretry-0.9.3.tar.gz",
            "has_sig": false,
            "md5_digest": "50783274085cf66b35bd69c7f131a473",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 1158465,
            "upload_time": "2023-12-21T19:18:00",
            "upload_time_iso_8601": "2023-12-21T19:18:00.607295Z",
            "url": "https://files.pythonhosted.org/packages/73/04/9ce6eca67cbe0f449e475bee91098e90e1a42083db3295023736b19e54f9/streamlit-drawable-canvas-jsretry-0.9.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-21 19:18:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "andfanilo",
    "github_project": "streamlit-drawable-canvas",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "streamlit-drawable-canvas-jsretry"
}
        
Elapsed time: 2.25725s