├── .gitignore ├── bower.json ├── package.json ├── LICENSE.md ├── README.md ├── example ├── index.html └── al-siq.js └── leaflet-touch-helper.js /.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leaflet-touch-helper", 3 | "version": "2.0.0", 4 | "homepage": "https://github.com/perliedman/leaflet-touch-helper", 5 | "authors": [ 6 | "Per Liedman (http://www.liedman.net/)" 7 | ], 8 | "description": "Make it easy to touch things in Leaflet", 9 | "keywords": ["leaflet", "touch"], 10 | "license": "ISC", 11 | "main": ["leaflet-touch-helper.js"] 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leaflet-touch-helper", 3 | "version": "2.0.0", 4 | "description": "Make it easy to touch things in Leaflet", 5 | "repository": "git@github.com:perliedman/leaflet-touch-helper.git", 6 | "homepage": "https://github.com/perliedman/leaflet-touch-helper", 7 | "main": "leaflet-touch-helper.js", 8 | "directories": { 9 | "example": "example" 10 | }, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": ["leaflet", "touch"], 15 | "author": "Per Liedman ", 16 | "license": "ISC" 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## ISC License 2 | 3 | Copyright (c) 2016, Per Liedman (per@liedman.net) 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Leaflet Touch Helper 2 | ==================== 3 | 4 | Make it easy to touch things in [Leaflet](http://leafletjs.com/). [See the demo](http://www.liedman.net/leaflet-touch-helper/). 5 | 6 | This plugin makes an invisible touch surface around paths, like polygons or polylines, to make it easier to hit them with your clumsy fingers. 7 | 8 | Technically, this plugin adds another, larger but transparent layer on top of the original layer, and forwards any events to the original layer. 9 | Depending on the number of layers and the complexity of your geometries, this might be expensive in terms of performance - you might want to use 10 | a more clever solution in those cases. For basics, this is easy and works well, though! 11 | 12 | ## Usage 13 | 14 | When adding a layer you want to make easy to touch, also create an instance of `L.Path.TouchHelper` and add to the map: 15 | 16 | ``` 17 | var polygon = L.polygon([ 18 | [51.509, -0.08], 19 | [51.503, -0.06], 20 | [51.51, -0.047] 21 | ]).addTo(mymap); 22 | 23 | L.path.touchHelper(polygon).addTo(map); 24 | ``` 25 | 26 | To explicitly add even more touch margin, for extra fat fingers, you can specify the `extraWeight` option: 27 | 28 | ``` 29 | L.path.touchHelper(polygon, {extraWeight: 50}).addTo(map); // Super fat 30 | ``` 31 | 32 | (Default for `extraWeight` is 25 pixels.) 33 | 34 | When the original layer is removed from the map, the touch helper layer will also be removed. Note however, 35 | that if you re-add the original layer, the touch helper layer _will not_ be re-added, you will have to create 36 | a new. (Technically, this is because there is no way to know if the layer is permanently removed or just 37 | temporarily; assuming that layers are always just temporarily removed would keep around _all_ created touch 38 | helper layers forever, which is rarely what you want.) 39 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Touch Helper demo 5 | 6 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 62 | 63 | -------------------------------------------------------------------------------- /leaflet-touch-helper.js: -------------------------------------------------------------------------------- 1 | !(function() { 2 | L.Path.TouchHelper = L[L.Layer ? 'Layer' : 'Class'].extend({ 3 | options: { 4 | extraWeight: 25 5 | }, 6 | 7 | initialize: function(path, options) { 8 | L.setOptions(this, options); 9 | this._sourceLayer = path; 10 | var touchPathOptions = L.extend({}, path.options, { opacity: 0, fillOpacity: 0 }); 11 | touchPathOptions.weight += this.options.extraWeight; 12 | 13 | if (path.eachLayer) { 14 | this._layer = L.layerGroup(); 15 | path.eachLayer(function(l) { 16 | if (l.eachLayer || l.getLatLngs) { 17 | this._layer.addLayer(L.path.touchHelper(l, L.extend({}, options, {parentLayer: this._layer}))); 18 | } 19 | }, this); 20 | } else if (path.getLatLngs) { 21 | this._layer = new path.constructor(path.getLatLngs(), touchPathOptions); 22 | this._layer.feature = path.feature; 23 | } else { 24 | throw new Error('Unknown layer type, neither a group or a path'); 25 | } 26 | 27 | this._layer.on('click dblclick mouseover mouseout mousemove', function(e) { 28 | (this.options.parentLayer ? this.options.parentLayer : path).fire(e.type, e); 29 | }, this); 30 | }, 31 | 32 | onAdd: function(map) { 33 | this._map = map; 34 | this._layer.addTo(map); 35 | if (!this.options.parentLayer) { 36 | map.on('layerremove', this._onLayerRemoved, this); 37 | } 38 | }, 39 | 40 | onRemove: function(map) { 41 | map.removeLayer(this._layer); 42 | map.off('layerremove', this._onLayerRemoved, this); 43 | this._map = null; 44 | }, 45 | 46 | addTo: function(map) { 47 | map.addLayer(this); 48 | }, 49 | 50 | _onLayerRemoved: function(e) { 51 | if (e.layer === this._sourceLayer) { 52 | this._map.removeLayer(this); 53 | } 54 | }, 55 | }); 56 | 57 | L.path = L.path || {}; 58 | 59 | L.path.touchHelper = function(path, options) { 60 | return new L.Path.TouchHelper(path, options); 61 | } 62 | })(); 63 | -------------------------------------------------------------------------------- /example/al-siq.js: -------------------------------------------------------------------------------- 1 | // The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 2 | var alSiq = { 3 | "type": "FeatureCollection", 4 | "generator": "overpass-turbo", 5 | "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.", 6 | "timestamp": "2016-10-13T07:31:02Z", 7 | "features": [ 8 | { 9 | "type": "Feature", 10 | "id": "way/35202567", 11 | "properties": { 12 | "@id": "way/35202567", 13 | "bicycle": "no", 14 | "foot": "yes", 15 | "highway": "track", 16 | "horse": "yes", 17 | "motor_vehicle": "no", 18 | "name": "Al-Siq", 19 | "name:ar": "السيق‎", 20 | "surface": "stone", 21 | "tracktype": "grade1", 22 | "waterway": "wadi" 23 | }, 24 | "geometry": { 25 | "type": "LineString", 26 | "coordinates": [ 27 | [ 28 | 35.4610716, 29 | 30.3218549 30 | ], 31 | [ 32 | 35.4608301, 33 | 30.3218881 34 | ], 35 | [ 36 | 35.4605812, 37 | 30.3218403 38 | ], 39 | [ 40 | 35.4601477, 41 | 30.3216875 42 | ], 43 | [ 44 | 35.4599238, 45 | 30.3215774 46 | ], 47 | [ 48 | 35.459843, 49 | 30.3214112 50 | ], 51 | [ 52 | 35.459764, 53 | 30.3213202 54 | ], 55 | [ 56 | 35.4597195, 57 | 30.3212133 58 | ], 59 | [ 60 | 35.4596774, 61 | 30.3211191 62 | ], 63 | [ 64 | 35.4595224, 65 | 30.3210579 66 | ], 67 | [ 68 | 35.4594195, 69 | 30.3210486 70 | ], 71 | [ 72 | 35.4592497, 73 | 30.3211709 74 | ], 75 | [ 76 | 35.4591003, 77 | 30.3212369 78 | ], 79 | [ 80 | 35.4589814, 81 | 30.3213691 82 | ], 83 | [ 84 | 35.4589309, 85 | 30.3214991 86 | ], 87 | [ 88 | 35.459007, 89 | 30.3216191 90 | ], 91 | [ 92 | 35.4590029, 93 | 30.3220169 94 | ], 95 | [ 96 | 35.4589277, 97 | 30.3221527 98 | ], 99 | [ 100 | 35.45888, 101 | 30.322328 102 | ], 103 | [ 104 | 35.4587813, 105 | 30.3223891 106 | ], 107 | [ 108 | 35.4586927, 109 | 30.3224693 110 | ], 111 | [ 112 | 35.4586317, 113 | 30.3226114 114 | ], 115 | [ 116 | 35.4585407, 117 | 30.3227531 118 | ], 119 | [ 120 | 35.4584817, 121 | 30.3228389 122 | ], 123 | [ 124 | 35.4583836, 125 | 30.3229085 126 | ], 127 | [ 128 | 35.4582605, 129 | 30.3229493 130 | ], 131 | [ 132 | 35.4581444, 133 | 30.323019 134 | ], 135 | [ 136 | 35.4580222, 137 | 30.323094 138 | ], 139 | [ 140 | 35.4578439, 141 | 30.3232221 142 | ], 143 | [ 144 | 35.457672, 145 | 30.3232433 146 | ], 147 | [ 148 | 35.4572346, 149 | 30.3232418 150 | ], 151 | [ 152 | 35.4570443, 153 | 30.3231377 154 | ], 155 | [ 156 | 35.4568297, 157 | 30.3230984 158 | ], 159 | [ 160 | 35.4566107, 161 | 30.3230304 162 | ], 163 | [ 164 | 35.4562393, 165 | 30.3228762 166 | ], 167 | [ 168 | 35.4560938, 169 | 30.3228525 170 | ], 171 | [ 172 | 35.4559857, 173 | 30.3228929 174 | ], 175 | [ 176 | 35.4558951, 177 | 30.3228197 178 | ], 179 | [ 180 | 35.4558515, 181 | 30.3227421 182 | ], 183 | [ 184 | 35.4557743, 185 | 30.3226861 186 | ], 187 | [ 188 | 35.4557278, 189 | 30.3225728 190 | ], 191 | [ 192 | 35.4556321, 193 | 30.3223993 194 | ], 195 | [ 196 | 35.4556133, 197 | 30.32229 198 | ], 199 | [ 200 | 35.4555082, 201 | 30.3222638 202 | ], 203 | [ 204 | 35.4554182, 205 | 30.3222002 206 | ], 207 | [ 208 | 35.4551321, 209 | 30.3221008 210 | ], 211 | [ 212 | 35.4550454, 213 | 30.3221466 214 | ], 215 | [ 216 | 35.4549578, 217 | 30.3222252 218 | ], 219 | [ 220 | 35.4549027, 221 | 30.3222885 222 | ], 223 | [ 224 | 35.4548528, 225 | 30.3223449 226 | ], 227 | [ 228 | 35.4548149, 229 | 30.3225502 230 | ], 231 | [ 232 | 35.4547744, 233 | 30.3226757 234 | ], 235 | [ 236 | 35.4547404, 237 | 30.3227409 238 | ], 239 | [ 240 | 35.4547214, 241 | 30.3228051 242 | ], 243 | [ 244 | 35.45458, 245 | 30.3228634 246 | ], 247 | [ 248 | 35.4543875, 249 | 30.322943 250 | ], 251 | [ 252 | 35.4542604, 253 | 30.3229579 254 | ], 255 | [ 256 | 35.4541525, 257 | 30.3229787 258 | ], 259 | [ 260 | 35.4540202, 261 | 30.3229203 262 | ], 263 | [ 264 | 35.4539246, 265 | 30.3229394 266 | ], 267 | [ 268 | 35.4537832, 269 | 30.3229122 270 | ], 271 | [ 272 | 35.4536606, 273 | 30.3229645 274 | ], 275 | [ 276 | 35.4535223, 277 | 30.3229054 278 | ], 279 | [ 280 | 35.4533777, 281 | 30.3228837 282 | ], 283 | [ 284 | 35.4532426, 285 | 30.3228256 286 | ], 287 | [ 288 | 35.4531383, 289 | 30.3227739 290 | ], 291 | [ 292 | 35.4531084, 293 | 30.3227257 294 | ], 295 | [ 296 | 35.4530571, 297 | 30.3226748 298 | ], 299 | [ 300 | 35.4529582, 301 | 30.3225619 302 | ], 303 | [ 304 | 35.4528713, 305 | 30.3225319 306 | ], 307 | [ 308 | 35.4527739, 309 | 30.3225025 310 | ], 311 | [ 312 | 35.4526847, 313 | 30.3224904 314 | ], 315 | [ 316 | 35.4525972, 317 | 30.3224199 318 | ], 319 | [ 320 | 35.4524739, 321 | 30.3223523 322 | ], 323 | [ 324 | 35.4523685, 325 | 30.3223443 326 | ], 327 | [ 328 | 35.4521767, 329 | 30.3223222 330 | ], 331 | [ 332 | 35.4520199, 333 | 30.3222697 334 | ], 335 | [ 336 | 35.4518963, 337 | 30.3222883 338 | ], 339 | [ 340 | 35.4515891, 341 | 30.3221628 342 | ], 343 | [ 344 | 35.4514324, 345 | 30.3224422 346 | ], 347 | [ 348 | 35.4512857, 349 | 30.3226255 350 | ], 351 | [ 352 | 35.4509722, 353 | 30.3227347 354 | ], 355 | [ 356 | 35.4504867, 357 | 30.3229267 358 | ], 359 | [ 360 | 35.4503117, 361 | 30.3230313 362 | ], 363 | [ 364 | 35.4500923, 365 | 30.3231624 366 | ], 367 | [ 368 | 35.4498091, 369 | 30.3233109 370 | ], 371 | [ 372 | 35.4494399, 373 | 30.323468 374 | ], 375 | [ 376 | 35.4492174, 377 | 30.323743 378 | ], 379 | [ 380 | 35.4490809, 381 | 30.3239525 382 | ], 383 | [ 384 | 35.4486764, 385 | 30.3238565 386 | ], 387 | [ 388 | 35.4479935, 389 | 30.3241144 390 | ] 391 | ] 392 | } 393 | }, 394 | { 395 | "type": "Feature", 396 | "id": "node/2437205265", 397 | "properties": { 398 | "@id": "node/2437205265", 399 | "name": "As-Siq gorge", 400 | "tourism": "attraction" 401 | }, 402 | "geometry": { 403 | "type": "Point", 404 | "coordinates": [ 405 | 35.4566107, 406 | 30.3230304 407 | ] 408 | } 409 | }, 410 | { 411 | "type": "Feature", 412 | "id": "node/2437205301", 413 | "properties": { 414 | "@id": "node/2437205301", 415 | "historic": "ruins", 416 | "name": "The Outer Siq", 417 | "tourism": "attraction" 418 | }, 419 | "geometry": { 420 | "type": "Point", 421 | "coordinates": [ 422 | 35.4503117, 423 | 30.3230313 424 | ] 425 | } 426 | } 427 | ] 428 | } --------------------------------------------------------------------------------