From ed16e8348b6670f29c253c875824b313773ebe12 Mon Sep 17 00:00:00 2001 From: jacobtoye Date: Tue, 5 Jun 2012 16:58:46 +1200 Subject: [PATCH] Adding initial files --- .gitattributes | 22 +++++ .gitignore | 165 ++++++++++++++++++++++++++++++++ Control.PolyDraw.css | 69 ++++++++++++++ Control.PolyDraw.js | 54 +++++++++++ Handler.PolyDraw.js | 222 +++++++++++++++++++++++++++++++++++++++++++ README.md | 30 ++++++ TODO.md | 4 + example/drawing.html | 31 ++++++ images/polygon.png | Bin 0 -> 318 bytes images/polyline.png | Bin 0 -> 266 bytes 10 files changed, 597 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 Control.PolyDraw.css create mode 100644 Control.PolyDraw.js create mode 100644 Handler.PolyDraw.js create mode 100644 README.md create mode 100644 TODO.md create mode 100644 example/drawing.html create mode 100644 images/polygon.png create mode 100644 images/polyline.png diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..412eeda78 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..aa8811c67 --- /dev/null +++ b/.gitignore @@ -0,0 +1,165 @@ + +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/** +tmp/** +tmp/**/* +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +**/[Dd]ebug/ +**/[Rr]elease/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +.builds +**/*.dotCover + +## TODO: If you have NuGet Package Restore enabled, uncomment this +#**/packages/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp + +# ReSharper is a .NET coding add-in +_ReSharper* + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Others +[Bb]in +[Oo]bj +sql +TestResults +*.Cache +ClientBin +stylecop.* +~$* +*.dbmdl +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + + + +############ +## Windows +############ + +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +# Mac crap +.DS_Store diff --git a/Control.PolyDraw.css b/Control.PolyDraw.css new file mode 100644 index 000000000..475663819 --- /dev/null +++ b/Control.PolyDraw.css @@ -0,0 +1,69 @@ +/* Leaflet controls */ + +.leaflet-control-polydraw { + -moz-border-radius: 7px; + -webkit-border-radius: 7px; + border-radius: 7px; + } +.leaflet-control-polydraw { + padding: 5px; + background: rgba(0, 0, 0, 0.25); + } +.leaflet-control-polydraw a { + background-color: rgba(255, 255, 255, 0.75); + } +.leaflet-control-polydraw a { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-control-polydraw a { + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + width: 19px; + height: 19px; + margin-top: 5px; + } +.leaflet-control-polydraw a:first-child{ + margin-top: 0; +} +.leaflet-control-polydraw a:hover { + background-color: #fff; + } +.leaflet-touch .leaflet-control-polydraw a { + width: 27px; + height: 27px; + } +.leaflet-control-polydraw-polyline { + background-image: url(images/polyline.png); + } +.leaflet-control-polydraw-polygon { + background-image: url(images/polygon.png); + } + +.leaflet-cursor-label { + background-color: #fff; + border: 1px solid #ccc; + color: #999; + font: 12px/18px "Helvetica Neue", Arial, Helvetica, sans-serif; + margin-left: 20px; + margin-top: -21px; + padding: 2px 4px; + position: absolute; + white-space: nowrap; + z-index: 6; +} + +.leaflet-cursor-label-latlng { + color: #222; +} + +.leaflet-polyline-guide-dash { + background-color: #f06eaa; + font-size: 1%; + opacity: 0.6; + position: absolute; + width: 5px; + height: 5px; +} \ No newline at end of file diff --git a/Control.PolyDraw.js b/Control.PolyDraw.js new file mode 100644 index 000000000..2cacb18d1 --- /dev/null +++ b/Control.PolyDraw.js @@ -0,0 +1,54 @@ +L.Control.PolyDraw = L.Control.extend({ + options: { + position: 'topleft', + drawPolyline: true, + drawPolygon: true + }, + + onAdd: function (map) { + var className = 'leaflet-control-polydraw', + container = L.DomUtil.create('div', className); + + if(this.options.drawPolyline) { + this._createButton( + 'Draw a polyline', + className + '-polyline', + container, + map.polyDraw.drawPolyline, + map.polyDraw + ); + } + + if(this.options.drawPolygon) { + this._createButton( + 'Draw a polygon', + className + '-polygon', + container, + map.polyDraw.drawPolygon, + map.polyDraw + ); + } + + return container; + }, + + _createButton: function (title, className, container, fn, context) { + var link = L.DomUtil.create('a', className, container); + link.href = '#'; + link.title = title; + + L.DomEvent + .addListener(link, 'click', L.DomEvent.stopPropagation) + .addListener(link, 'click', L.DomEvent.preventDefault) + .addListener(link, 'click', fn, context); + + return link; + } +}); + +L.Map.addInitHook(function () { + if (this.options.polyDrawControl) { + this.polyDrawControl = new L.Control.PolyDraw(); + this.addControl(this.polyDrawControl); + } +}); \ No newline at end of file diff --git a/Handler.PolyDraw.js b/Handler.PolyDraw.js new file mode 100644 index 000000000..9a2b55f45 --- /dev/null +++ b/Handler.PolyDraw.js @@ -0,0 +1,222 @@ +L.Handler.PolyDraw = L.Handler.extend({ + options: { + icon: new L.DivIcon({ + iconSize: new L.Point(8, 8), + className: 'leaflet-div-icon leaflet-editing-icon' + }), + guidelineDistance: 20 + }, + + initialize: function (map, options) { + this._map = map; + this._container = map._container; + this._pane = map._panes.overlayPane; + + L.Util.setOptions(this, options); + }, + + addHooks: function () { + if (this._map) { + this._markers = []; + + this._markerGroup = new L.LayerGroup(); + this._map.addLayer(this._markerGroup); + + this._poly = new L.Polyline([], { color: '#f06eaa' }); + + //create the label if haven't before + if (!this._cursorLabel) { + this._cursorLabel = L.DomUtil.create('div', 'leaflet-cursor-label', this._pane); + } + this._cursorLabel.style.display = 'block'; + + //TODO refactor: move cursor to styles + this._container.style.cursor = 'crosshair'; + + L.DomEvent + .addListener(this._container, 'mousemove', this._onMouseMove, this) + .addListener(this._container, 'click', this._onClick, this); + } + }, + + removeHooks: function () { + if (this._map) { + var poly; + + if (this._polyOptions.type === 'polygon') { + poly = new L.Polygon(this._poly.getLatLngs(), { color: '#f06eaa' }); + } else { + poly = new L.Polyline(this._poly.getLatLngs(), { color: '#f06eaa' }); + } + + this._map.fire('polycreated', { poly: poly }); + + if (this._markers.length > 0) { + this._markers[0].off('click', this.disable); + } + + //remove markers from map + this._map.removeLayer(this._markerGroup); + delete this._markerGroup; + delete this._markers; + + this._map.removeLayer(this._poly); + delete this._poly; + + //clean up DOM + this._clearGuides(); + this._cursorLabel.style.display = 'none'; + + //TODO refactor: move cursor to styles + this._container.style.cursor = ''; + + L.DomEvent + .removeListener(this._container, 'mousemove', this._onMouseMove) + .removeListener(this._container, 'click', this._onClick); + } + }, + + drawPolyline: function () { + this._polyOptions = { + type: 'polyline', + getLabelText: function (markerCount) { + var text; + if (markerCount === 0) { + text = 'Click to start drawing line.'; + } else if (markerCount === 1) { + text = 'Click to continue drawing line.'; + } else { + text = 'Click last point to finish line.'; + } + return text; + } + }; + this.enable(); + }, + + drawPolygon: function () { + this._polyOptions = { + type: 'polygon', + getLabelText: function (markerCount) { + var text; + if (markerCount === 0) { + text = 'Click to start drawing shape.'; + } else if (markerCount < 3) { + text = 'Click to continue drawing shape.'; + } else { + text = 'Click first point to close this shape.'; + } + return text; + } + }; + this.enable(); + }, + + _createMarker: function (latlng) { + var marker = new L.Marker(latlng, { + icon: this.options.icon + }); + + this._markerGroup.addLayer(marker); + + return marker; + }, + + _onMouseMove: function (e) { + var newPos = this._map.mouseEventToLayerPoint(e), + latlng = this._map.mouseEventToLatLng(e), + markerCount = this._markers.length; + + // update the label + L.DomUtil.setPosition(this._cursorLabel, newPos); + this._setToolipText(latlng, this._polyOptions.getLabelText(markerCount)); + + // draw the guides + if (markerCount > 0) { + this._clearGuides(); + this._drawGuide( + this._map.latLngToLayerPoint(this._markers[markerCount - 1].getLatLng()), + newPos + ); + } + + L.DomEvent.preventDefault(e); + }, + + _onClick: function (e) { + var latlng = this._map.mouseEventToLatLng(e), + marker = this._createMarker(latlng); + + // Add close handler to appropriate point + if ((this._polyOptions.type === 'polygon' && this._markers.length === 0) || + (this._polyOptions.type === 'polyline' && this._markers.length > 0) + ) { + marker.on('click', this.disable, this); + } + + // Remove the close handler from the last point and add to new marker + if (this._polyOptions.type === 'polyline' && this._markers.length !== 0) { + this._markers[this._markers.length - 1].off('click', this.disable); + } + + this._markers.push(marker); + + this._poly.addLatLng(latlng); + + if (this._poly.getLatLngs().length === 2) { + this._map.addLayer(this._poly); + } + }, + + _setToolipText: function (latlng, text) { + this._cursorLabel.innerHTML = + '' + + latlng.lat.toFixed(6) + + ', ' + + latlng.lng.toFixed(6) + + '' + + '
' + + '' + text + ''; + }, + + // removes all child elements (guide dashes) from the guides container + _clearGuides: function () { + if (this._guidesContainer) { + while (this._guidesContainer.firstChild) { + this._guidesContainer.removeChild(this._guidesContainer.firstChild); + } + } + }, + + _drawGuide: function (pointA, pointB) { + var length = Math.floor(Math.sqrt(Math.pow((pointB.x - pointA.x), 2) + Math.pow((pointB.y - pointA.y), 2))), + i, + fraction, + dashPoint, + dash; + + //create the guides container if we haven't yet (TODO: probaly shouldn't do this every time the user starts to draw?) + if (!this._guidesContainer) { + this._guidesContainer = L.DomUtil.create('div', 'leaflet-polyline-guides', this._pane); + } + + //draw a dash every GuildeLineDistance + for (i = this.options.guidelineDistance; i < length; i += this.options.guidelineDistance) { + //work out fraction along line we are + fraction = i / length; + + //calculate new x,y point + dashPoint = { + x: Math.floor((pointA.x * (1 - fraction)) + (fraction * pointB.x)), + y: Math.floor((pointA.y * (1 - fraction)) + (fraction * pointB.y)) + }; + + //add guide dash to guide container + dash = L.DomUtil.create('div', 'leaflet-polyline-guide-dash', this._guidesContainer); + + L.DomUtil.setPosition(dash, dashPoint); + } + } +}); + +L.Map.addInitHook('addHandler', 'polyDraw', L.Handler.PolyDraw); \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 000000000..2b3fed853 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +#Leaflet.draw +Adds support for drawing polys to Leaflet. + +This plugin is based on @brunob's [draw plugin](https://github.com/brunob/leaflet.draw). I decided to create a new repo rather than forking as I wanted to take the coding style and functionality in a different direction. + +#Using the plugin +If you are happy with the control being displayed below the zoom controls just set ````polyDrawControl = true```` when declaring your Leaflet map. + +E.g.: + +```` +var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', +cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18}), +map = new L.Map('map', {layers: [cloudmade], center: new L.LatLng(-37.7772, 175.2756), zoom: 15, polyDrawControl: true }); +```` + +If you would like to reposition the control or turn off poly type add the control manually: + +```` +var drawControl = new L.Control.Draw({ + position: 'topright', + drawPolyline: false +}); +map.addControl(drawControl); +```` + +See [example/map-polydraw.html](https://github.com/jacobtoye/Leaflet.iconlabel/blob/master/example/map-marker-iconlabels.html) for a working example. + +#Official support +Leaflet plan to include drawing in 0.4 so this is just a band-aid until it comes. See https://github.com/CloudMade/Leaflet/issues/174 \ No newline at end of file diff --git a/TODO.md b/TODO.md new file mode 100644 index 000000000..0c0d72701 --- /dev/null +++ b/TODO.md @@ -0,0 +1,4 @@ + - ability to change colour + - add support for esc = cancel + - use distance instead of lat/lng + - add in rectangle and marker \ No newline at end of file diff --git a/example/drawing.html b/example/drawing.html new file mode 100644 index 000000000..9044d7fdf --- /dev/null +++ b/example/drawing.html @@ -0,0 +1,31 @@ + + + + Leaflet PolyDraw + + + + + + + + + + +
+ + + + diff --git a/images/polygon.png b/images/polygon.png new file mode 100644 index 0000000000000000000000000000000000000000..579102ddb69e7ead8e7e8f757dfc487de367acb9 GIT binary patch literal 318 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@wC9V-A!TD(=<%vb942~)JNvR5+ zxryniL8*x;m4zo$ZGeg%c)B=-RNR^}aUtI!2cEY6#^fZS&I87sa~wW%JrL|Mm&j+} zoW{U+yrNmsq~gc~VU=hmCieQ1^(RvcPG)@4-5d9R+jY&ax!GTrcRpZs3uT>D!R|dF zOz?*SyCTPdqnCV>CR)f@H1e`C9<_XLqqbbewnU;p^HLdG_=faPENc!hA5rRZWZ&Yo zIOm}7nFAsz57dsn`XM5-kiV}@O69ItLWbZDof$Kf zHdhZbIovJpu>^C#$ptWRk1 zIrhnZ#TSho>eqc>{WHb*SPo