vendor: 15,983 bytes, lines 1-478
1(function (global, factory) { 2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('leaflet')) : 3 typeof define === 'function' && define.amd ? define(['leaflet'], factory) : 4 (factory(global.L)); 5}(this, (function (L$1) { 'use strict'; 6 7L$1 = L$1 && L$1.hasOwnProperty('default') ? L$1['default'] : L$1; 8 9// functional re-impl of L.Point.distanceTo, 10// with no dependency on Leaflet for easier testing 11function pointDistance(ptA, ptB) { 12 var x = ptB.x - ptA.x; 13 var y = ptB.y - ptA.y; 14 return Math.sqrt(x * x + y * y); 15} 16 17var computeSegmentHeading = function computeSegmentHeading(a, b) { 18 return (Math.atan2(b.y - a.y, b.x - a.x) * 180 / Math.PI + 90 + 360) % 360; 19}; 20 21var asRatioToPathLength = function asRatioToPathLength(_ref, totalPathLength) { 22 var value = _ref.value, 23 isInPixels = _ref.isInPixels; 24 return isInPixels ? value / totalPathLength : value; 25}; 26 27function parseRelativeOrAbsoluteValue(value) { 28 if (typeof value === 'string' && value.indexOf('%') !== -1) { 29 return { 30 value: parseFloat(value) / 100, 31 isInPixels: false 32 }; 33 } 34 var parsedValue = value ? parseFloat(value) : 0; 35 return { 36 value: parsedValue, 37 isInPixels: parsedValue > 0 38 }; 39} 40 41var pointsEqual = function pointsEqual(a, b) { 42 return a.x === b.x && a.y === b.y; 43}; 44 45function pointsToSegments(pts) { 46 return pts.reduce(function (segments, b, idx, points) { 47 // this test skips same adjacent points 48 if (idx > 0 && !pointsEqual(b, points[idx - 1])) { 49 var a = points[idx - 1]; 50 var distA = segments.length > 0 ? segments[segments.length - 1].distB : 0; 51 var distAB = pointDistance(a, b); 52 segments.push({ 53 a: a, 54 b: b, 55 distA: distA, 56 distB: distA + distAB, 57 heading: computeSegmentHeading(a, b) 58 }); 59 } 60 return segments; 61 }, []); 62} 63 64function projectPatternOnPointPath(pts, pattern) { 65 // 1. split the path into segment infos 66 var segments = pointsToSegments(pts); 67 var nbSegments = segments.length; 68 if (nbSegments === 0) { 69 return []; 70 } 71 72 var totalPathLength = segments[nbSegments - 1].distB; 73 74 var offset = asRatioToPathLength(pattern.offset, totalPathLength); 75 var endOffset = asRatioToPathLength(pattern.endOffset, totalPathLength); 76 var repeat = asRatioToPathLength(pattern.repeat, totalPathLength); 77 78 var repeatIntervalPixels = totalPathLength * repeat; 79 var startOffsetPixels = offset > 0 ? totalPathLength * offset : 0; 80 var endOffsetPixels = endOffset > 0 ? totalPathLength * endOffset : 0; 81 82 // 2. generate the positions of the pattern as offsets from the path start 83 var positionOffsets = []; 84 var positionOffset = startOffsetPixels; 85 do { 86 positionOffsets.push(positionOffset); 87 positionOffset += repeatIntervalPixels; 88 } while (repeatIntervalPixels > 0 && positionOffset < totalPathLength - endOffsetPixels); 89 90 // 3. projects offsets to segments 91 var segmentIndex = 0; 92 var segment = segments[0]; 93 return positionOffsets.map(function (positionOffset) { 94 // find the segment matching the offset, 95 // starting from the previous one as offsets are ordered 96 while (positionOffset > segment.distB && segmentIndex < nbSegments - 1) { 97 segmentIndex++; 98 segment = segments[segmentIndex]; 99 } 100 101 var segmentRatio = (positionOffset - segment.distA) / (segment.distB - segment.distA); 102 return { 103 pt: interpolateBetweenPoints(segment.a, segment.b, segmentRatio), 104 heading: segment.heading 105 }; 106 }); 107} 108 109/** 110* Finds the point which lies on the segment defined by points A and B, 111* at the given ratio of the distance from A to B, by linear interpolation. 112*/ 113function interpolateBetweenPoints(ptA, ptB, ratio) { 114 if (ptB.x !== ptA.x) { 115 return { 116 x: ptA.x + ratio * (ptB.x - ptA.x), 117 y: ptA.y + ratio * (ptB.y - ptA.y) 118 }; 119 } 120 // special case where points lie on the same vertical axis 121 return { 122 x: ptA.x, 123 y: ptA.y + (ptB.y - ptA.y) * ratio 124 }; 125} 126 127(function() { 128 // save these original methods before they are overwritten 129 var proto_initIcon = L.Marker.prototype._initIcon; 130 var proto_setPos = L.Marker.prototype._setPos; 131 132 var oldIE = (L.DomUtil.TRANSFORM === 'msTransform'); 133 134 L.Marker.addInitHook(function () { 135 var iconOptions = this.options.icon && this.options.icon.options; 136 var iconAnchor = iconOptions && this.options.icon.options.iconAnchor; 137 if (iconAnchor) { 138 iconAnchor = (iconAnchor[0] + 'px ' + iconAnchor[1] + 'px'); 139 } 140 this.options.rotationOrigin = this.options.rotationOrigin || iconAnchor || 'center bottom' ; 141 this.options.rotationAngle = this.options.rotationAngle || 0; 142 143 // Ensure marker keeps rotated during dragging 144 this.on('drag', function(e) { e.target._applyRotation(); }); 145 }); 146 147 L.Marker.include({ 148 _initIcon: function() { 149 proto_initIcon.call(this); 150 }, 151 152 _setPos: function (pos) { 153 proto_setPos.call(this, pos); 154 this._applyRotation(); 155 }, 156 157 _applyRotation: function () { 158 if(this.options.rotationAngle) { 159 this._icon.style[L.DomUtil.TRANSFORM+'Origin'] = this.options.rotationOrigin; 160 161 if(oldIE) { 162 // for IE 9, use the 2D rotation 163 this._icon.style[L.DomUtil.TRANSFORM] = 'rotate(' + this.options.rotationAngle + 'deg)'; 164 } else { 165 // for modern browsers, prefer the 3D accelerated version 166 this._icon.style[L.DomUtil.TRANSFORM] += ' rotateZ(' + this.options.rotationAngle + 'deg)'; 167 } 168 } 169 }, 170 171 setRotationAngle: function(angle) { 172 this.options.rotationAngle = angle; 173 this.update(); 174 return this; 175 }, 176 177 setRotationOrigin: function(origin) { 178 this.options.rotationOrigin = origin; 179 this.update(); 180 return this; 181 } 182 }); 183})(); 184 185L$1.Symbol = L$1.Symbol || {}; 186 187/** 188* A simple dash symbol, drawn as a Polyline. 189* Can also be used for dots, if 'pixelSize' option is given the 0 value. 190*/ 191L$1.Symbol.Dash = L$1.Class.extend({ 192 options: { 193 pixelSize: 10, 194 pathOptions: {} 195 }, 196 197 initialize: function initialize(options) { 198 L$1.Util.setOptions(this, options); 199 this.options.pathOptions.clickable = false; 200 }, 201 202 buildSymbol: function buildSymbol(dirPoint, latLngs, map, index, total) { 203 var opts = this.options; 204 var d2r = Math.PI / 180; 205 206 // for a dot, nothing more to compute 207 if (opts.pixelSize <= 1) { 208 return L$1.polyline([dirPoint.latLng, dirPoint.latLng], opts.pathOptions); 209 } 210 211 var midPoint = map.project(dirPoint.latLng); 212 var angle = -(dirPoint.heading - 90) * d2r; 213 var a = L$1.point(midPoint.x + opts.pixelSize * Math.cos(angle + Math.PI) / 2, midPoint.y + opts.pixelSize * Math.sin(angle) / 2); 214 // compute second point by central symmetry to avoid unecessary cos/sin 215 var b = midPoint.add(midPoint.subtract(a)); 216 return L$1.polyline([map.unproject(a), map.unproject(b)], opts.pathOptions); 217 } 218}); 219 220L$1.Symbol.dash = function (options) { 221 return new L$1.Symbol.Dash(options); 222}; 223 224L$1.Symbol.ArrowHead = L$1.Class.extend({ 225 options: { 226 polygon: true, 227 pixelSize: 10, 228 headAngle: 60, 229 pathOptions: { 230 stroke: false, 231 weight: 2 232 } 233 }, 234 235 initialize: function initialize(options) { 236 L$1.Util.setOptions(this, options); 237 this.options.pathOptions.clickable = false; 238 }, 239 240 buildSymbol: function buildSymbol(dirPoint, latLngs, map, index, total) { 241 return this.options.polygon ? L$1.polygon(this._buildArrowPath(dirPoint, map), this.options.pathOptions) : L$1.polyline(this._buildArrowPath(dirPoint, map), this.options.pathOptions); 242 }, 243 244 _buildArrowPath: function _buildArrowPath(dirPoint, map) { 245 var d2r = Math.PI / 180; 246 var tipPoint = map.project(dirPoint.latLng); 247 var direction = -(dirPoint.heading - 90) * d2r; 248 var radianArrowAngle = this.options.headAngle / 2 * d2r; 249 250 var headAngle1 = direction + radianArrowAngle; 251 var headAngle2 = direction - radianArrowAngle; 252 var arrowHead1 = L$1.point(tipPoint.x - this.options.pixelSize * Math.cos(headAngle1), tipPoint.y + this.options.pixelSize * Math.sin(headAngle1)); 253 var arrowHead2 = L$1.point(tipPoint.x - this.options.pixelSize * Math.cos(headAngle2), tipPoint.y + this.options.pixelSize * Math.sin(headAngle2)); 254 255 return [map.unproject(arrowHead1), dirPoint.latLng, map.unproject(arrowHead2)]; 256 } 257}); 258 259L$1.Symbol.arrowHead = function (options) { 260 return new L$1.Symbol.ArrowHead(options); 261}; 262 263L$1.Symbol.Marker = L$1.Class.extend({ 264 options: { 265 markerOptions: {}, 266 rotate: false 267 }, 268 269 initialize: function initialize(options) { 270 L$1.Util.setOptions(this, options); 271 this.options.markerOptions.clickable = false; 272 this.options.markerOptions.draggable = false; 273 }, 274 275 buildSymbol: function buildSymbol(directionPoint, latLngs, map, index, total) { 276 if (this.options.rotate) { 277 this.options.markerOptions.rotationAngle = directionPoint.heading + (this.options.angleCorrection || 0); 278 } 279 return L$1.marker(directionPoint.latLng, this.options.markerOptions); 280 } 281}); 282 283L$1.Symbol.marker = function (options) { 284 return new L$1.Symbol.Marker(options); 285}; 286 287var isCoord = function isCoord(c) { 288 return c instanceof L$1.LatLng || Array.isArray(c) && c.length === 2 && typeof c[0] === 'number'; 289}; 290 291var isCoordArray = function isCoordArray(ll) { 292 return Array.isArray(ll) && isCoord(ll[0]); 293}; 294 295L$1.PolylineDecorator = L$1.FeatureGroup.extend({ 296 options: { 297 patterns: [] 298 }, 299 300 initialize: function initialize(paths, options) { 301 L$1.FeatureGroup.prototype.initialize.call(this); 302 L$1.Util.setOptions(this, options); 303 this._map = null; 304 this._paths = this._initPaths(paths); 305 this._bounds = this._initBounds(); 306 this._patterns = this._initPatterns(this.options.patterns); 307 }, 308 309 /** 310 * Deals with all the different cases. input can be one of these types: 311 * array of LatLng, array of 2-number arrays, Polyline, Polygon, 312 * array of one of the previous. 313 */ 314 _initPaths: function _initPaths(input, isPolygon) { 315 var _this = this; 316 317 if (isCoordArray(input)) { 318 // Leaflet Polygons don't need the first point to be repeated, but we do 319 var coords = isPolygon ? input.concat([input[0]]) : input; 320 return [coords]; 321 } 322 if (input instanceof L$1.Polyline) { 323 // we need some recursivity to support multi-poly* 324 return this._initPaths(input.getLatLngs(), input instanceof L$1.Polygon); 325 } 326 if (Array.isArray(input)) { 327 // flatten everything, we just need coordinate lists to apply patterns 328 return input.reduce(function (flatArray, p) { 329 return flatArray.concat(_this._initPaths(p, isPolygon)); 330 }, []); 331 } 332 return []; 333 }, 334 335 // parse pattern definitions and precompute some values 336 _initPatterns: function _initPatterns(patternDefs) { 337 return patternDefs.map(this._parsePatternDef); 338 }, 339 340 /** 341 * Changes the patterns used by this decorator 342 * and redraws the new one. 343 */ 344 setPatterns: function setPatterns(patterns) { 345 this.options.patterns = patterns; 346 this._patterns = this._initPatterns(this.options.patterns); 347 this.redraw(); 348 }, 349 350 /** 351 * Changes the patterns used by this decorator 352 * and redraws the new one. 353 */ 354 setPaths: function setPaths(paths) { 355 this._paths = this._initPaths(paths); 356 this._bounds = this._initBounds(); 357 this.redraw(); 358 }, 359 360 /** 361 * Parse the pattern definition 362 */ 363 _parsePatternDef: function _parsePatternDef(patternDef, latLngs) { 364 return { 365 symbolFactory: patternDef.symbol, 366 // Parse offset and repeat values, managing the two cases: 367 // absolute (in pixels) or relative (in percentage of the polyline length) 368 offset: parseRelativeOrAbsoluteValue(patternDef.offset), 369 endOffset: parseRelativeOrAbsoluteValue(patternDef.endOffset), 370 repeat: parseRelativeOrAbsoluteValue(patternDef.repeat) 371 }; 372 }, 373 374 onAdd: function onAdd(map) { 375 this._map = map; 376 this._draw(); 377 this._map.on('moveend', this.redraw, this); 378 }, 379 380 onRemove: function onRemove(map) { 381 this._map.off('moveend', this.redraw, this); 382 this._map = null; 383 L$1.FeatureGroup.prototype.onRemove.call(this, map); 384 }, 385 386 /** 387 * As real pattern bounds depends on map zoom and bounds, 388 * we just compute the total bounds of all paths decorated by this instance. 389 */ 390 _initBounds: function _initBounds() { 391 var allPathCoords = this._paths.reduce(function (acc, path) { 392 return acc.concat(path); 393 }, []); 394 return L$1.latLngBounds(allPathCoords); 395 }, 396 397 getBounds: function getBounds() { 398 return this._bounds; 399 }, 400 401 /** 402 * Returns an array of ILayers object 403 */ 404 _buildSymbols: function _buildSymbols(latLngs, symbolFactory, directionPoints) { 405 var _this2 = this; 406 407 return directionPoints.map(function (directionPoint, i) { 408 return symbolFactory.buildSymbol(directionPoint, latLngs, _this2._map, i, directionPoints.length); 409 }); 410 }, 411 412 /** 413 * Compute pairs of LatLng and heading angle, 414 * that define positions and directions of the symbols on the path 415 */ 416 _getDirectionPoints: function _getDirectionPoints(latLngs, pattern) { 417 var _this3 = this; 418 419 if (latLngs.length < 2) { 420 return []; 421 } 422 var pathAsPoints = latLngs.map(function (latLng) { 423 return _this3._map.project(latLng); 424 }); 425 return projectPatternOnPointPath(pathAsPoints, pattern).map(function (point) { 426 return { 427 latLng: _this3._map.unproject(L$1.point(point.pt)), 428 heading: point.heading 429 }; 430 }); 431 }, 432 433 redraw: function redraw() { 434 if (!this._map) { 435 return; 436 } 437 this.clearLayers(); 438 this._draw(); 439 }, 440 441 /** 442 * Returns all symbols for a given pattern as an array of FeatureGroup 443 */ 444 _getPatternLayers: function _getPatternLayers(pattern) { 445 var _this4 = this; 446 447 var mapBounds = this._map.getBounds().pad(0.1); 448 return this._paths.map(function (path) { 449 var directionPoints = _this4._getDirectionPoints(path, pattern) 450 // filter out invisible points 451 .filter(function (point) { 452 return mapBounds.contains(point.latLng); 453 }); 454 return L$1.featureGroup(_this4._buildSymbols(path, pattern.symbolFactory, directionPoints)); 455 }); 456 }, 457 458 /** 459 * Draw all patterns 460 */ 461 _draw: function _draw() { 462 var _this5 = this; 463 464 this._patterns.map(function (pattern) { 465 return _this5._getPatternLayers(pattern); 466 }).forEach(function (layers) { 467 _this5.addLayer(L$1.featureGroup(layers)); 468 }); 469 } 470}); 471/* 472 * Allows compact syntax to be used 473 */ 474L$1.polylineDecorator = function (paths, options) { 475 return new L$1.PolylineDecorator(paths, options); 476}; 477 478})));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.