UNPKG

leaflet

Version:

JavaScript library for mobile-friendly interactive maps

124 lines (99 loc) 3.4 kB
/* * L.Renderer is a base class for renderer implementations (SVG, Canvas); * handles renderer container, bounds and zoom animation. */ L.Renderer = L.Layer.extend({ options: { // how much to extend the clip area around the map view (relative to its size) // e.g. 0.1 would be 10% of map view in each direction; defaults to clip with the map view padding: 0.1 }, initialize: function (options) { L.setOptions(this, options); L.stamp(this); }, onAdd: function () { if (!this._container) { this._initContainer(); // defined by renderer implementations if (this._zoomAnimated) { L.DomUtil.addClass(this._container, 'leaflet-zoom-animated'); } } this.getPane().appendChild(this._container); this._update(); }, onRemove: function () { L.DomUtil.remove(this._container); }, getEvents: function () { var events = { viewreset: this._reset, zoomstart: this._onZoomStart, zoom: this._onZoom, moveend: this._update }; if (this._zoomAnimated) { events.zoomanim = this._onAnimZoom; } return events; }, _onAnimZoom: function (ev) { this._updateTransform(ev.center, ev.zoom); }, _onZoom: function () { this._updateTransform(this._map.getCenter(), this._map.getZoom()); }, _onZoomStart: function () { // Drag-then-pinch interactions might mess up the center and zoom. // In this case, the easiest way to prevent this is re-do the renderer // bounds and padding when the zooming starts. this._update(); }, _updateTransform: function (center, zoom) { var scale = this._map.getZoomScale(zoom, this._zoom), position = L.DomUtil.getPosition(this._container), viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding), currentCenterPoint = this._map.project(this._center, zoom), destCenterPoint = this._map.project(center, zoom), centerOffset = destCenterPoint.subtract(currentCenterPoint), topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(viewHalf).subtract(centerOffset); L.DomUtil.setTransform(this._container, topLeftOffset, scale); }, _reset: function () { this._update(); this._updateTransform(this._center, this._zoom); }, _update: function () { // update pixel bounds of renderer container (for positioning/sizing/clipping later) var p = this.options.padding, size = this._map.getSize(), min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round(); this._bounds = new L.Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round()); this._center = this._map.getCenter(); this._zoom = this._map.getZoom(); } }); L.Map.include({ // used by each vector layer to decide which renderer to use getRenderer: function (layer) { var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer; if (!renderer) { renderer = this._renderer = (this.options.preferCanvas && L.canvas()) || L.svg(); } if (!this.hasLayer(renderer)) { this.addLayer(renderer); } return renderer; }, _getPaneRenderer: function (name) { if (name === 'overlayPane' || name === undefined) { return false; } var renderer = this._paneRenderers[name]; if (renderer === undefined) { renderer = (L.SVG && L.svg({pane: name})) || (L.Canvas && L.canvas({pane: name})); this._paneRenderers[name] = renderer; } return renderer; } });