@progress/kendo-charts
Version:
Kendo UI platform-independent Charts library
420 lines (333 loc) • 11.9 kB
JavaScript
import {
geometry as g,
drawing as d
} from '@progress/kendo-drawing';
import {
Class,
defined,
last,
setDefaultOptions
} from '../../common';
import {
proxy
} from '../utils';
import {
Layer
} from './layer';
import {
Movable
} from '../scroller/draggable';
import {
Location
} from '../location';
var Group = d.Group;
export var ShapeLayer = (function (Layer) {
function ShapeLayer(map, options) {
Layer.call(this, map, options);
this._pan = proxy(this._pan, this);
this.surface = d.Surface.create(this.element, {
width: map.scrollElement.clientWidth,
height: map.scrollElement.clientHeight
});
this._initRoot();
this.movable = new Movable(this.surface.element);
this._markers = [];
this._click = this._handler('shapeClick');
this.surface.bind('click', this._click);
this._mouseleave = this._handler('shapeMouseLeave');
this.surface.bind('mouseleave', this._mouseleave);
this.surface.bind('mouseenter', this._mouseenter.bind(this));
}
if ( Layer ) ShapeLayer.__proto__ = Layer;
ShapeLayer.prototype = Object.create( Layer && Layer.prototype );
ShapeLayer.prototype.constructor = ShapeLayer;
ShapeLayer.prototype.destroy = function destroy () {
Layer.prototype.destroy.call(this);
this.surface.destroy();
};
ShapeLayer.prototype._reset = function _reset () {
Layer.prototype._reset.call(this);
this._translateSurface();
this._data = this._readData();
if (this._hasData()) {
this._load(this._data);
}
};
ShapeLayer.prototype._initRoot = function _initRoot () {
this._root = new Group();
this.surface.draw(this._root);
};
ShapeLayer.prototype._beforeReset = function _beforeReset () {
this.surface.clear();
this._initRoot();
};
ShapeLayer.prototype._resize = function _resize () {
this.surface.size(this.map.size());
};
ShapeLayer.prototype._readData = function _readData () {
var data = Layer.prototype._readData.call(this);
if (data.type === "FeatureCollection") {
return data.features;
}
if (data.type === "GeometryCollection") {
return data.geometries;
}
return data;
};
ShapeLayer.prototype._load = function _load (data) {
var this$1 = this;
this._data = data;
this._clearMarkers();
if (!this._loader) {
this._loader = new GeoJsonLoader(this.map, this.options.style, this);
}
var container = new Group();
for (var i = 0; i < data.length; i++) {
var shape = this$1._loader.parse(data[i]);
if (shape) {
container.append(shape);
}
}
this._root.clear();
this._root.append(container);
};
ShapeLayer.prototype.shapeCreated = function shapeCreated (shape) {
var cancelled = false;
// the GeoJSON loader builds "Point" type as a circle
// use the circle shape type as and indicator for rendering a marker
// keep the behavior under a setting as this is supported by kendo jQuery Map
// but we opted out of this in blazor
if (shape instanceof d.Circle && this.map.options.renderPointsAsMarkers) {
cancelled = defined(this._createMarker(shape));
}
if (!cancelled) {
var args = {
layer: this,
shape: shape
};
cancelled = this.map.trigger('shapeCreated', args);
}
return cancelled;
};
ShapeLayer.prototype.featureCreated = function featureCreated (e) {
e.layer = this;
this.map.trigger('shapeFeatureCreated', e);
};
ShapeLayer.prototype._createMarker = function _createMarker (shape) {
var marker = this.map.markers.bind({
location: shape.location
}, shape.dataItem);
if (marker) {
this._markers.push(marker);
}
return marker;
};
ShapeLayer.prototype._clearMarkers = function _clearMarkers () {
var this$1 = this;
for (var i = 0; i < this._markers.length; i++) {
this$1.map.markers.remove(this$1._markers[i]);
}
this._markers = [];
};
ShapeLayer.prototype._pan = function _pan () {
if (!this._panning) {
this._panning = true;
this.surface.suspendTracking();
}
};
ShapeLayer.prototype._panEnd = function _panEnd (e) {
Layer.prototype._panEnd.call(this, e);
this._translateSurface();
this.surface.resumeTracking();
this._panning = false;
};
ShapeLayer.prototype._translateSurface = function _translateSurface () {
var map = this.map;
var nw = map.locationToView(map.extent().nw);
if (this.surface.translate) {
this.surface.translate(nw);
this.movable.moveTo({
x: nw.x,
y: nw.y
});
}
};
ShapeLayer.prototype._eventArgs = function _eventArgs (e) {
return {
layer: this,
layerIndex: this._layerIndex(),
shape: e.element,
shapeIndex: (this._data || []).indexOf(e.element.dataItem),
originalEvent: e.originalEvent
};
};
ShapeLayer.prototype._handler = function _handler (eventName) {
var this$1 = this;
return function (e) {
if (e.element) {
this$1.map.trigger(eventName, this$1._eventArgs(e));
}
};
};
ShapeLayer.prototype._mouseenter = function _mouseenter (e) {
if (!e.element) {
return;
}
this.map.trigger('shapeMouseEnter', this._eventArgs(e));
var shape = e.element;
var anchor = this._tooltipAnchor(e);
this.map._tooltip.show(anchor, this._tooltipContext(shape));
};
ShapeLayer.prototype._tooltipContext = function _tooltipContext (shape) {
return {
type: 'shape',
layerIndex: this._layerIndex(),
className: 'k-map-shape-tooltip',
dataItem: shape.dataItem,
location: shape.location
};
};
ShapeLayer.prototype._tooltipAnchor = function _tooltipAnchor (e) {
var cursor = this.map.eventOffset(e.originalEvent);
return {
top: cursor.y,
left: cursor.x
};
};
ShapeLayer.prototype._activate = function _activate () {
Layer.prototype._activate.call(this);
this._panHandler = proxy(this._pan, this);
this.map.bind('pan', this.panHandler);
};
ShapeLayer.prototype._deactivate = function _deactivate () {
Layer.prototype._deactivate.call(this);
this.map.unbind('pan', this._panHandler);
};
return ShapeLayer;
}(Layer));
setDefaultOptions(ShapeLayer, {
autoBind: true,
zIndex: 100
});
var GeoJsonLoader = (function (Class) {
function GeoJsonLoader(locator, defaultStyle, observer) {
Class.call(this);
this.observer = observer;
this.locator = locator;
this.style = defaultStyle;
}
if ( Class ) GeoJsonLoader.__proto__ = Class;
GeoJsonLoader.prototype = Object.create( Class && Class.prototype );
GeoJsonLoader.prototype.constructor = GeoJsonLoader;
GeoJsonLoader.prototype.parse = function parse (item) {
var root = new Group();
var unwrap = true;
if (item.type === 'Feature') {
unwrap = false;
this._loadGeometryTo(root, item.geometry, item);
this._featureCreated(root, item);
} else {
this._loadGeometryTo(root, item, item);
}
if (unwrap && root.children.length < 2) {
root = root.children[0];
}
return root;
};
GeoJsonLoader.prototype._shapeCreated = function _shapeCreated (shape) {
var cancelled = false;
if (this.observer && this.observer.shapeCreated) {
cancelled = this.observer.shapeCreated(shape);
}
return cancelled;
};
GeoJsonLoader.prototype._featureCreated = function _featureCreated (group, dataItem) {
if (this.observer && this.observer.featureCreated) {
this.observer.featureCreated({
group: group,
dataItem: dataItem,
properties: dataItem.properties
});
}
};
GeoJsonLoader.prototype._loadGeometryTo = function _loadGeometryTo (container, geometry, dataItem) {
var this$1 = this;
var coords = geometry.coordinates;
var i;
var path;
switch (geometry.type) {
case 'LineString':
path = this._loadPolygon(container, [coords], dataItem);
this._setLineFill(path);
break;
case 'MultiLineString':
for (i = 0; i < coords.length; i++) {
path = this$1._loadPolygon(container, [coords[i]], dataItem);
this$1._setLineFill(path);
}
break;
case 'Polygon':
this._loadPolygon(container, coords, dataItem);
break;
case 'MultiPolygon':
for (i = 0; i < coords.length; i++) {
this$1._loadPolygon(container, coords[i], dataItem);
}
break;
case 'Point':
this._loadPoint(container, coords, dataItem);
break;
case 'MultiPoint':
for (i = 0; i < coords.length; i++) {
this$1._loadPoint(container, coords[i], dataItem);
}
break;
default:
break;
}
};
GeoJsonLoader.prototype._setLineFill = function _setLineFill (path) {
var segments = path.segments;
if (segments.length < 4 || !segments[0].anchor().equals(last(segments).anchor())) {
path.options.fill = null;
}
};
GeoJsonLoader.prototype._loadShape = function _loadShape (container, shape) {
if (!this._shapeCreated(shape)) {
container.append(shape);
}
return shape;
};
GeoJsonLoader.prototype._loadPolygon = function _loadPolygon (container, rings, dataItem) {
var shape = this._buildPolygon(rings);
shape.dataItem = dataItem;
shape.location = this.locator.viewToLocation(shape.bbox().center());
return this._loadShape(container, shape);
};
GeoJsonLoader.prototype._buildPolygon = function _buildPolygon (rings) {
var this$1 = this;
var type = rings.length > 1 ? d.MultiPath : d.Path;
var path = new type(this.style);
for (var i = 0; i < rings.length; i++) {
for (var j = 0; j < rings[i].length; j++) {
var point = this$1.locator.locationToView(Location.fromLngLat(rings[i][j]));
if (j === 0) {
path.moveTo(point.x, point.y);
} else {
path.lineTo(point.x, point.y);
}
}
}
return path;
};
GeoJsonLoader.prototype._loadPoint = function _loadPoint (container, coords, dataItem) {
var location = Location.fromLngLat(coords);
var point = this.locator.locationToView(location);
var circle = new g.Circle(point, 10);
var shape = new d.Circle(circle, this.style);
shape.dataItem = dataItem;
shape.location = location;
return this._loadShape(container, shape);
};
return GeoJsonLoader;
}(Class));