{"id":15387186,"url":"https://github.com/wildhoney/leaflet.freedraw","last_synced_at":"2025-05-15T03:05:45.045Z","repository":{"id":19783283,"uuid":"23042153","full_name":"Wildhoney/Leaflet.FreeDraw","owner":"Wildhoney","description":":earth_asia: FreeDraw allows the free-hand drawing of shapes on your Leaflet.js map layer – providing an intuitive and familiar UX for creating geospatial boundaries similar to Zoopla and others. Included out-of-the-box is the concaving of polygons, polygon merging and simplifying, as well as the ability to add edges and modify existing shapes.","archived":false,"fork":false,"pushed_at":"2025-05-08T12:03:53.000Z","size":18938,"stargazers_count":556,"open_issues_count":61,"forks_count":104,"subscribers_count":29,"default_branch":"master","last_synced_at":"2025-05-08T13:22:26.118Z","etag":null,"topics":["draw","geospatial","maps","markers","polygon","shape","zoopla"],"latest_commit_sha":null,"homepage":"https://freedraw.herokuapp.com/","language":"JavaScript","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/Wildhoney.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2014-08-17T14:22:33.000Z","updated_at":"2025-05-08T12:03:56.000Z","dependencies_parsed_at":"2025-02-12T07:08:36.209Z","dependency_job_id":"9e1fffff-e0b5-4a83-b823-2c71b71b71cc","html_url":"https://github.com/Wildhoney/Leaflet.FreeDraw","commit_stats":null,"previous_names":[],"tags_count":148,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wildhoney%2FLeaflet.FreeDraw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wildhoney%2FLeaflet.FreeDraw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wildhoney%2FLeaflet.FreeDraw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wildhoney%2FLeaflet.FreeDraw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Wildhoney","download_url":"https://codeload.github.com/Wildhoney/Leaflet.FreeDraw/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264765,"owners_count":22041793,"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":["draw","geospatial","maps","markers","polygon","shape","zoopla"],"created_at":"2024-10-01T14:52:27.098Z","updated_at":"2025-05-15T03:05:44.997Z","avatar_url":"https://github.com/Wildhoney.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"example/media/logo.png\" width=\"400\" /\u003e\n\n\u003e FreeDraw allows the free-hand drawing of shapes on your Leaflet.js map layer \u0026ndash; providing an intuitive and familiar UX for creating geospatial boundaries similar to [Zoopla](http://www.zoopla.co.uk/for-sale/map/property/london/?include_retirement_homes=true\u0026include_shared_ownership=true\u0026new_homes=include\u0026q=London\u0026results_sort=newest_listings\u0026search_source=home\u0026pn=1\u0026view_type=map) and others. Included out-of-the-box is the [concaving of polygons](http://ubicomp.algoritmi.uminho.pt/local/concavehull.html), polygon merging and simplifying, as well as the ability to add edges and modify existing shapes.\n\u003e **Note:** For drawing polylines instead, try [`L.Pather`](https://github.com/Wildhoney/L.Pather).\n\n![Travis](http://img.shields.io/travis/Wildhoney/Leaflet.FreeDraw.svg?style=flat-square)\n\u0026nbsp;\n![npm](http://img.shields.io/npm/v/leaflet-freedraw.svg?style=flat-square)\n\u0026nbsp;\n![Bower](https://img.shields.io/bower/v/bootstrap.svg?style=flat-square)\n\u0026nbsp;\n![MIT License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square)\n\n* **npm:** `npm i leaflet-freedraw`\n* **Bower:** `bower i leaflet-freedraw`\n* **JSFiddle:** https://jsfiddle.net/0dzhs5Lg/3/\n\n## Table of Contents\n\n1. [Browser Support](#browser-support)\n2. [Getting Started](#getting-started)\n  1. [Markers](#adding-markers)\n  2. [Modes](#setting-modes)\n  3. [Options](#passing-options)\n  4. [Classes](#classes)\n  5. [Methods](#bundled-methods)\n  6. [Predefined Polygons](#predefined-polygons)\n\n![FreeDraw Screenshot](example/media/screenshot.png)\n\n## Browser Support\n\n\u003cimg src=\"https://github.com/alrra/browser-logos/blob/37.2.1/chrome/chrome_128x128.png?raw=true\" width=\"64\" /\u003e \u003cimg src=\"https://github.com/alrra/browser-logos/blob/37.2.1/opera/opera_128x128.png?raw=true\" width=\"64\" /\u003e \u003cimg src=\"https://github.com/alrra/browser-logos/blob/37.2.1/firefox/firefox_128x128.png?raw=true\" width=\"64\" /\u003e \u003cimg src=\"https://github.com/alrra/browser-logos/blob/37.2.1/internet-explorer/internet-explorer_128x128.png?raw=true\" width=\"64\" alt=\"IE10 onwards\" /\u003e \u003cimg src=\"https://github.com/alrra/browser-logos/blob/37.2.1/edge/edge_128x128.png?raw=true\" width=\"64\" /\u003e \u003cimg src=\"https://github.com/alrra/browser-logos/blob/37.2.1/safari/safari_128x128.png?raw=true\" width=\"64\" /\u003e\n\n## Getting Started\n\n`FreeDraw` functions as a standard Leaflet module, meaning you initialise it and add it to your map layer via the `addLayer` function on your map instance \u0026ndash; when you instantiate `FreeDraw` you can pass a set of [`options`](#passing-options) for behaviour customisation.\n\n```javascript\nimport L from 'leaflet';\nimport FreeDraw from 'leaflet-freedraw';\n\nconst map = new L.Map(node);\nconst freeDraw = new FreeDraw();\n\nmap.addLayer(freeDraw);\n```\n\nBy attaching `FreeDraw` to your map layer, an SVG node will be appended to the DOM, and mouse event listeners will be attached to the `map` instance for creating and managing the geospatial polygons.\n\n## Adding Markers\n\nWhen a user creates a polygon an event is fired on the `map` instance called `markers` which you can listen for by using the native Leaflet `on` function.\n\n```javascript\nfreeDraw.on('markers', event =\u003e {\n    console.log(event.latLngs);\n});\n```\n\n**Note:** You can obtain the event type through the `event.eventType` field \u0026ndash; such as `create`, `edit`, etc...\n\nOnce you have received the latitude and longitude values the next step would likely be to perform any necessary geospatial queries, and then render the relevant markers onto the map \u0026ndash; for this you *could* use `L.Marker` and the native `addTo` method for [placing markers](http://leafletjs.com/reference-1.0.2.html#marker) on the map \u0026ndash; however the important take-away is that `FreeDraw` doesn't concern itself with marker placement, as this is sufficiently covered by Leaflet.\n\n## Setting Modes\n\nBy default the mode is `ALL` which means all actions can be performed on the `FreeDraw` layer \u0026mdash; create, edit, delete, and append \u0026mdash; you're able to modify the mode at any time by using the `mode` method, or upon instantiation by passing an object as the first argument.\n\n```javascript\nimport L from 'leaflet';\nimport FreeDraw, { CREATE, EDIT } from 'leaflet-freedraw';\n\nconst map = new L.Map(node);\nconst freeDraw = new FreeDraw({\n    mode: CREATE | EDIT\n});\n```\n\nBy passing in the `mode` as `CREATE | EDIT` you're **only** allowing the user to create and edit polygons, they are not able to append edges, nor delete them. You may use the `mode` method post-instantiation to modify the `mode` at any time \u0026ndash; in the case below to also allow deleting of polygons.\n\n```javascript\n// Allow create, edit and delete.\nfreeDraw.mode(CREATE | EDIT | DELETE);\n\n// Allow everything except create.\nfreeDraw.mode(ALL ^ CREATE);\n\n// Allow nothing.\nfreeDraw.mode(NONE);\n```\n\n\u003e Note: Invoking `mode` without passing a mode simply returns the current mode.\n\n## Passing Options\n\nAll of the following options can be passed in when instantiating `FreeDraw` in the same way that we pass `mode` in the previous examples.\n\n| Option                 | Default      | Result                               |\n| ---------------------- |------------- | ------------------------------------ |\n| `mode`                 | `ALL`        | Modifies the default [mode](#setting-modes). |\n| `smoothFactor`         | `0.3`        | By how much to [smooth](http://leafletjs.com/reference-1.0.2.html#polyline-smoothfactor) the polygons.  |\n| `elbowDistance`        | `10`         | Factor to determine when to delete or when to append an edge.  |\n| `simplifyFactor`       | `1.1`        | By how much to [simplify](https://sourceforge.net/p/jsclipper/wiki/documentation/#clipperlibclippercleanpolygon) the polygon.  |\n| `mergePolygons`        | `true`       | Whether to attempt merging of polygons that intersect.  |\n| `concavePolygon`       | `true`       | Whether to apply the [concaving algorithm](http://ubicomp.algoritmi.uminho.pt/local/concavehull.html) to the polygons.  |\n| `maximumPolygons`      | `Infinity`   | Maximum number of polygons to be added to the map layer.  |\n| `notifyAfterEditExit`  | `false`      | Whether to defer `markers` event until after exiting `EDIT` mode.  |\n| `leaveModeAfterCreate` | `false`      | Whether to exit `CREATE` mode after each polygon creation.  |\n| `strokeWidth`          | `2`          | Size of the stroke when drawing. |\n\nBy using the options above we can tweak how `FreeDraw` functions \u0026ndash; whilst some of the options have obvious effects, others are much more *tweak and see* based on your expected outcome \u0026ndash; such as the subjective `simplifyFactor` and `elbowDistance` options.\n\n## Classes\n\nDepending on the current modes active on the map instance, the relevant classes are applied to the `map` container that you instantiated `L.Map` with \u0026ndash; by using these class names it allows you to tailor the UX to the current mode, such as changing the `cursor` to `crosshair` when the user is allowed to create polygons.\n\n| Class Name          | Mode         |\n| ------------------- |------------- |\n| `mode-none`         | `NONE`       |\n| `mode-create`       | `CREATE`     |\n| `mode-edit`         | `EDIT`       |\n| `mode-delete`       | `DELETE`     |\n| `mode-append`       | `APPEND`     |\n\n```css\n.map.mode-create {\n    cursor: crosshair;\n}\n```\n\nFrom the above example if the current mode is `CREATE | EDIT | APPEND` then the **three** class names that will be present on the `map` node will be `mode-create`, `mode-edit` and `mode-append`, allowing you to provide a better UX from within your attached stylesheet.\n\n### Bundled Methods\n\nWith the instance of `freeDraw` there are certain methods for manipulating `FreeDraw` directly, such as creating polygon from a set of latitude and longitude values.\n\n| Method              | Yields       | Result                                                         |\n| ------------------- |------------- | -------------------------------------------------------------- |\n| `create`            | `Array`      | Creates a polygon by passing an array of `LatLng`s             |\n| `remove`            | `void`       | Removes a polygon that is yielded from `create`                |\n| `clear`             | `void`       | Clears all polygons from the current instance                  |\n| `mode`              | `Number`     | Sets and retrieves the current [`mode`](#setting-modes).               |\n| `cancel`            | `void`       | Cancels the current create action \u0026ndash; such as on escape.   |\n| `size`              | `Number`     | Yields the number of polygons on the map layer.                |\n| `all`               | `Array`      | Enumerate all of the current polygons for the current layer    |\n\nWhen using the `create` method to create polygons from an array of latitude and longitude values, the `CREATE` mode is disregarded, which means it doesn't need to be enabled to `create` to succeed \u0026ndash; if you would like such behaviour then you could simply assert that `CREATE` is enabled.\n\n```javascript\nimport L, { LatLng } from 'leaflet';\nimport FreeDraw from 'leaflet-freedraw';\n\nconst map = new L.Map(node);\nconst freeDraw = new FreeDraw();\n\n// Create a polygon based on the given lat/long values.\nconst polygons = freeDraw.create([\n    new LatLng(51.50046151184328, -0.08771896362304689),\n    new LatLng(51.50067523261736, -0.09175300598144533),\n    new LatLng(51.50329323076107, -0.09106636047363283),\n    new LatLng(51.50409462869737, -0.08763313293457033)\n]);\n\n// Remove the created polygons from the map.\npolygons.forEach(polygon =\u003e freeDraw.remove(polygon));\n\n// Alternatively you could have cleared ALL polygons.\nfreeDraw.clear();\n```\n\n**Note:** `create` method returns an array of polygons, as often it may yield more than one.\n\nIn the case of the `cancel` method it's often desirable to cancel the creation of the polygon when the escape key is pressed \u0026ndash; for this you simply need to attach an event to the `document.body`.\n\n```javascript\ndocument.addEventListener('keydown', event =\u003e {\n\n    // Cancel the current action when the escape key is pressed.\n    event.key === 'Escape' \u0026\u0026 freeDraw.cancel();\n\n});\n```\n\n## Predefined Polygons\n\nYou can add polygons to the map layer at any point by using the `create` method. You **must** remember to [setup `FreeDraw` through Leaflet](#getting-started), rather than instantiating `FreeDraw` without tying it to a Leaflet map instance.\n\n```javascript\nfreeDraw.create([\n    new L.LatLng(51.50046151184328, -0.08771896362304689),\n    new L.LatLng(51.50067523261736, -0.09175300598144533),\n    new L.LatLng(51.50329323076107, -0.09106636047363283),\n    new L.LatLng(51.50409462869737, -0.08763313293457033)\n]);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwildhoney%2Fleaflet.freedraw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwildhoney%2Fleaflet.freedraw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwildhoney%2Fleaflet.freedraw/lists"}