{"id":13937887,"url":"https://github.com/andfanilo/streamlit-drawable-canvas","last_synced_at":"2025-03-13T14:07:22.914Z","repository":{"id":38354494,"uuid":"262818995","full_name":"andfanilo/streamlit-drawable-canvas","owner":"andfanilo","description":"Do you like Quick, Draw? Well what if you could train/predict doodles drawn inside Streamlit? Also draws lines, circles and boxes over background images for annotation.","archived":false,"fork":false,"pushed_at":"2024-08-09T17:07:26.000Z","size":9395,"stargazers_count":624,"open_issues_count":67,"forks_count":94,"subscribers_count":13,"default_branch":"develop","last_synced_at":"2025-02-27T15:22:09.250Z","etag":null,"topics":["drawing","fabric","image-annotation","python","react","streamlit"],"latest_commit_sha":null,"homepage":"https://drawable-canvas.streamlit.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andfanilo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-10T15:37:54.000Z","updated_at":"2025-02-24T02:50:09.000Z","dependencies_parsed_at":"2023-10-20T17:06:14.366Z","dependency_job_id":"cc210819-b11c-498c-9a83-439bd51b9850","html_url":"https://github.com/andfanilo/streamlit-drawable-canvas","commit_stats":{"total_commits":86,"total_committers":11,"mean_commits":7.818181818181818,"dds":0.2441860465116279,"last_synced_commit":"e9c74ad9f58e8ae6d51c3b4320f1851f7858584c"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andfanilo%2Fstreamlit-drawable-canvas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andfanilo%2Fstreamlit-drawable-canvas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andfanilo%2Fstreamlit-drawable-canvas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andfanilo%2Fstreamlit-drawable-canvas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andfanilo","download_url":"https://codeload.github.com/andfanilo/streamlit-drawable-canvas/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243419073,"owners_count":20287805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drawing","fabric","image-annotation","python","react","streamlit"],"created_at":"2024-08-07T23:04:00.008Z","updated_at":"2025-03-13T14:07:22.890Z","avatar_url":"https://github.com/andfanilo.png","language":"TypeScript","funding_links":["https://www.buymeacoffee.com/andfanilo"],"categories":["TypeScript"],"sub_categories":[],"readme":"# Streamlit - Drawable Canvas\n\n---\n\nThis project is [unmaintained](https://www.youtube.com/watch?v=1RFJF_ETpLk). \n\n Please add a thumbs up [HERE](https://github.com/streamlit/streamlit/issues/875) if you wish to see a native implementation.\n\n---\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\u003ca href=\"https://www.buymeacoffee.com/andfanilo\" target=\"_blank\"\u003e\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" height=\"50\" width=\"180\"\u003e\u003c/a\u003e\n\n![](./img/demo.gif)\n\n## Features\n\n- Draw freely, lines, circles, boxes and polygons on the canvas, with options on stroke \u0026 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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandfanilo%2Fstreamlit-drawable-canvas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandfanilo%2Fstreamlit-drawable-canvas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandfanilo%2Fstreamlit-drawable-canvas/lists"}