/* * Vector rendering for all browsers that support canvas. */ L.Browser.canvas = (function () { return !!document.createElement('canvas').getContext; }()); L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({ statics: { //CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value CANVAS: true, SVG: false }, redraw: function () { if (this._map) { this.projectLatlngs(); this._requestUpdate(); } return this; }, setStyle: function (style) { L.setOptions(this, style); if (this._map) { this._updateStyle(); this._requestUpdate(); } return this; }, onRemove: function (map) { map .off('viewreset', this.projectLatlngs, this) .off('moveend', this._updatePath, this); if (this.options.clickable) { this._map.off('click', this._onClick, this); this._map.off('mousemove', this._onMouseMove, this); } this._requestUpdate(); this._map = null; }, _requestUpdate: function () { if (this._map && !L.Path._updateRequest) { L.Path._updateRequest = L.Util.requestAnimFrame(this._fireMapMoveEnd, this._map); } }, _fireMapMoveEnd: function () { L.Path._updateRequest = null; this.fire('moveend'); }, _initElements: function () { this._map._initPathRoot(); this._ctx = this._map._canvasCtx; }, _updateStyle: function () { var options = this.options; if (options.stroke) { this._ctx.lineWidth = options.weight; this._ctx.strokeStyle = options.color; } if (options.fill) { this._ctx.fillStyle = options.fillColor || options.color; } }, _drawPath: function () { var i, j, len, len2, point, drawMethod; this._ctx.beginPath(); for (i = 0, len = this._parts.length; i < len; i++) { for (j = 0, len2 = this._parts[i].length; j < len2; j++) { point = this._parts[i][j]; drawMethod = (j === 0 ? 'move' : 'line') + 'To'; this._ctx[drawMethod](point.x, point.y); } // TODO refactor ugly hack if (this instanceof L.Polygon) { this._ctx.closePath(); } } }, _checkIfEmpty: function () { return !this._parts.length; }, _updatePath: function () { if (this._checkIfEmpty()) { return; } var ctx = this._ctx, options = this.options; this._drawPath(); ctx.save(); this._updateStyle(); if (options.fill) { ctx.globalAlpha = options.fillOpacity; ctx.fill(); } if (options.stroke) { ctx.globalAlpha = options.opacity; ctx.stroke(); } ctx.restore(); // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature }, _initEvents: function () { if (this.options.clickable) { // TODO dblclick this._map.on('mousemove', this._onMouseMove, this); this._map.on('click', this._onClick, this); } }, _onClick: function (e) { if (this._containsPoint(e.layerPoint)) { this.fire('click', e); } }, _onMouseMove: function (e) { if (!this._map || this._map._animatingZoom) { return; } // TODO don't do on each move if (this._containsPoint(e.layerPoint)) { this._ctx.canvas.style.cursor = 'pointer'; this._mouseInside = true; this.fire('mouseover', e); } else if (this._mouseInside) { this._ctx.canvas.style.cursor = ''; this._mouseInside = false; this.fire('mouseout', e); } } }); L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : { _initPathRoot: function () { var root = this._pathRoot, ctx; if (!root) { root = this._pathRoot = document.createElement('canvas'); root.style.position = 'absolute'; ctx = this._canvasCtx = root.getContext('2d'); ctx.lineCap = 'round'; ctx.lineJoin = 'round'; this._panes.overlayPane.appendChild(root); if (this.options.zoomAnimation) { this._pathRoot.className = 'leaflet-zoom-animated'; this.on('zoomanim', this._animatePathZoom); this.on('zoomend', this._endPathZoom); } this.on('moveend', this._updateCanvasViewport); this._updateCanvasViewport(); } }, _updateCanvasViewport: function () { // don't redraw while zooming. See _updateSvgViewport for more details if (this._pathZooming) { return; } this._updatePathViewport(); var vp = this._pathViewport, min = vp.min, size = vp.max.subtract(min), root = this._pathRoot; //TODO check if this works properly on mobile webkit L.DomUtil.setPosition(root, min); root.width = size.x; root.height = size.y; root.getContext('2d').translate(-min.x, -min.y); } });