Current File : //home/tradevaly/www/node_modules/leaflet/src/layer/vector/SVG.js |
import {Renderer} from './Renderer';
import * as DomUtil from '../../dom/DomUtil';
import * as DomEvent from '../../dom/DomEvent';
import * as Browser from '../../core/Browser';
import {stamp} from '../../core/Util';
import {svgCreate, pointsToPath} from './SVG.Util';
export {pointsToPath};
import {vmlMixin, vmlCreate} from './SVG.VML';
export var create = Browser.vml ? vmlCreate : svgCreate;
/*
* @class SVG
* @inherits Renderer
* @aka L.SVG
*
* Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG).
* Inherits `Renderer`.
*
* Due to [technical limitations](http://caniuse.com/#search=svg), SVG is not
* available in all web browsers, notably Android 2.x and 3.x.
*
* Although SVG is not available on IE7 and IE8, these browsers support
* [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language)
* (a now deprecated technology), and the SVG renderer will fall back to VML in
* this case.
*
* @example
*
* Use SVG by default for all paths in the map:
*
* ```js
* var map = L.map('map', {
* renderer: L.svg()
* });
* ```
*
* Use a SVG renderer with extra padding for specific vector geometries:
*
* ```js
* var map = L.map('map');
* var myRenderer = L.svg({ padding: 0.5 });
* var line = L.polyline( coordinates, { renderer: myRenderer } );
* var circle = L.circle( center, { renderer: myRenderer } );
* ```
*/
export var SVG = Renderer.extend({
getEvents: function () {
var events = Renderer.prototype.getEvents.call(this);
events.zoomstart = this._onZoomStart;
return events;
},
_initContainer: function () {
this._container = create('svg');
// makes it possible to click through svg root; we'll reset it back in individual paths
this._container.setAttribute('pointer-events', 'none');
this._rootGroup = create('g');
this._container.appendChild(this._rootGroup);
},
_destroyContainer: function () {
DomUtil.remove(this._container);
DomEvent.off(this._container);
delete this._container;
delete this._rootGroup;
delete this._svgSize;
},
_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();
},
_update: function () {
if (this._map._animatingZoom && this._bounds) { return; }
Renderer.prototype._update.call(this);
var b = this._bounds,
size = b.getSize(),
container = this._container;
// set size of svg-container if changed
if (!this._svgSize || !this._svgSize.equals(size)) {
this._svgSize = size;
container.setAttribute('width', size.x);
container.setAttribute('height', size.y);
}
// movement: update container viewBox so that we don't have to change coordinates of individual layers
DomUtil.setPosition(container, b.min);
container.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));
this.fire('update');
},
// methods below are called by vector layers implementations
_initPath: function (layer) {
var path = layer._path = create('path');
// @namespace Path
// @option className: String = null
// Custom class name set on an element. Only for SVG renderer.
if (layer.options.className) {
DomUtil.addClass(path, layer.options.className);
}
if (layer.options.interactive) {
DomUtil.addClass(path, 'leaflet-interactive');
}
this._updateStyle(layer);
this._layers[stamp(layer)] = layer;
},
_addPath: function (layer) {
if (!this._rootGroup) { this._initContainer(); }
this._rootGroup.appendChild(layer._path);
layer.addInteractiveTarget(layer._path);
},
_removePath: function (layer) {
DomUtil.remove(layer._path);
layer.removeInteractiveTarget(layer._path);
delete this._layers[stamp(layer)];
},
_updatePath: function (layer) {
layer._project();
layer._update();
},
_updateStyle: function (layer) {
var path = layer._path,
options = layer.options;
if (!path) { return; }
if (options.stroke) {
path.setAttribute('stroke', options.color);
path.setAttribute('stroke-opacity', options.opacity);
path.setAttribute('stroke-width', options.weight);
path.setAttribute('stroke-linecap', options.lineCap);
path.setAttribute('stroke-linejoin', options.lineJoin);
if (options.dashArray) {
path.setAttribute('stroke-dasharray', options.dashArray);
} else {
path.removeAttribute('stroke-dasharray');
}
if (options.dashOffset) {
path.setAttribute('stroke-dashoffset', options.dashOffset);
} else {
path.removeAttribute('stroke-dashoffset');
}
} else {
path.setAttribute('stroke', 'none');
}
if (options.fill) {
path.setAttribute('fill', options.fillColor || options.color);
path.setAttribute('fill-opacity', options.fillOpacity);
path.setAttribute('fill-rule', options.fillRule || 'evenodd');
} else {
path.setAttribute('fill', 'none');
}
},
_updatePoly: function (layer, closed) {
this._setPath(layer, pointsToPath(layer._parts, closed));
},
_updateCircle: function (layer) {
var p = layer._point,
r = Math.max(Math.round(layer._radius), 1),
r2 = Math.max(Math.round(layer._radiusY), 1) || r,
arc = 'a' + r + ',' + r2 + ' 0 1,0 ';
// drawing a circle with two half-arcs
var d = layer._empty() ? 'M0 0' :
'M' + (p.x - r) + ',' + p.y +
arc + (r * 2) + ',0 ' +
arc + (-r * 2) + ',0 ';
this._setPath(layer, d);
},
_setPath: function (layer, path) {
layer._path.setAttribute('d', path);
},
// SVG does not have the concept of zIndex so we resort to changing the DOM order of elements
_bringToFront: function (layer) {
DomUtil.toFront(layer._path);
},
_bringToBack: function (layer) {
DomUtil.toBack(layer._path);
}
});
if (Browser.vml) {
SVG.include(vmlMixin);
}
// @namespace SVG
// @factory L.svg(options?: Renderer options)
// Creates a SVG renderer with the given options.
export function svg(options) {
return Browser.svg || Browser.vml ? new SVG(options) : null;
}