echarts-extension-leaflet
Version:
echarts extension for leaflet
224 lines (191 loc) • 6.95 kB
JavaScript
import { util, graphic, matrix } from 'echarts/lib/echarts';
import L from 'leaflet/src/Leaflet';
// import {extendTilerLayerToDelGap} from './L.TileLayer.NoGap'
import './L.TileLayer.NoGap'
import DesignTileLayer from './L.TileLayer.define.theme'
/**
* constructor for Leaflet CoordSys
* @param {L.map} map
* @param {Object} api
*/
function LeafletCoordSys(map, api) {
this._map = map;
this.dimensions = ['lng', 'lat'];
this._mapOffset = [0, 0];
this._api = api;
this._projection = L.Projection.Mercator;
}
LeafletCoordSys.prototype.dimensions = ['lng', 'lat'];
LeafletCoordSys.prototype.setZoom = function(zoom) {
this._zoom = zoom;
};
LeafletCoordSys.prototype.setCenter = function(center) {
this._center = this._projection.project(new L.LatLng(center[1], center[0]));
};
LeafletCoordSys.prototype.setMapOffset = function(mapOffset) {
this._mapOffset = mapOffset;
};
LeafletCoordSys.prototype.getLeaflet = function() {
return this._map;
};
LeafletCoordSys.prototype.dataToPoint = function(data) {
const point = new L.LatLng(data[1], data[0]);
const px = this._map.latLngToLayerPoint(point);
const mapOffset = this._mapOffset;
return [px.x - mapOffset[0], px.y - mapOffset[1]];
};
LeafletCoordSys.prototype.pointToData = function(pt) {
const mapOffset = this._mapOffset;
const coord = this._map.layerPointToLatLng({
x: pt[0] + mapOffset[0],
y: pt[1] + mapOffset[1],
});
return [coord.lng, coord.lat];
};
LeafletCoordSys.prototype.convertToPixel = util.curry(
doConvert,
'dataToPoint'
);
LeafletCoordSys.prototype.convertFromPixel = util.curry(
doConvert,
'pointToData'
);
/**
* find appropriate coordinate system to convert
* @param {*} methodName
* @param {*} ecModel
* @param {*} finder
* @param {*} value
* @return {*} converted value
*/
function doConvert(methodName, ecModel, finder, value) {
let leafletModel = finder.leafletModel;
let seriesModel = finder.seriesModel;
let coordSys = leafletModel
? leafletModel.coordinateSystem
: seriesModel
? seriesModel.coordinateSystem || // For map.
(seriesModel.getReferringComponents('leaflet')[0] || {})
.coordinateSystem
: null;
/* eslint-disable no-invalid-this */
return coordSys === this ? coordSys[methodName](value) : null;
}
LeafletCoordSys.prototype.getViewRect = function() {
const api = this._api;
return new graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight());
};
LeafletCoordSys.prototype.getRoamTransform = function() {
return matrix.create();
};
LeafletCoordSys.dimensions = LeafletCoordSys.prototype.dimensions;
const CustomOverlay = L.Layer.extend({
initialize: function(container) {
this._container = container;
},
onAdd: function(map) {
let pane = map.getPane(this.options.pane);
pane.appendChild(this._container);
// Calculate initial position of container with
// `L.Map.latLngToLayerPoint()`, `getPixelOrigin()
// and/or `getPixelBounds()`
// L.DomUtil.setPosition(this._container, point);
// Add and position children elements if needed
// map.on('zoomend viewreset', this._update, this);
},
onRemove: function(map) {
L.DomUtil.remove(this._container);
// map.off('zoomend viewreset', this._update, this);
},
_update: function() {
// Recalculate position of container
// L.DomUtil.setPosition(this._container, point);
// Add/remove/reposition children elements if needed
},
});
LeafletCoordSys.create = function(ecModel, api) {
let leafletCoordSys;
let leafletList = [];
const root = api.getDom();
// TODO Dispose
ecModel.eachComponent('leaflet', function(leafletModel) {
let viewportRoot = api.getZr().painter.getViewportRoot();
if (typeof L === 'undefined') {
throw new Error('Leaflet api is not loaded');
}
if (leafletCoordSys) {
throw new Error('Only one leaflet component can exist');
}
if (!leafletModel.__map) {
// Not support IE8
let mapRoot = root.querySelector('.ec-extension-leaflet');
if (mapRoot) {
// Reset viewport left and top, which will be changed
// in moving handler in LeafletView
viewportRoot.style.left = '0px';
viewportRoot.style.top = '0px';
root.removeChild(mapRoot);
}
mapRoot = document.createElement('div');
mapRoot.style.cssText = 'width:100%;height:100%';
// Not support IE8
mapRoot.classList.add('ec-extension-leaflet');
root.appendChild(mapRoot);
let map = (leafletModel.__map = L.map(mapRoot, leafletModel.get('leafletOption')));
const tiles = leafletModel.get('tiles');
let baseLayers = {};
let baseLayerAdded = false;
for (let tile of tiles) {
// let tileLayer = L.tileLayer(tile.urlTemplate, tile.options);
let tileLayer = new DesignTileLayer(tile.urlTemplate, tile.options);
if (tile.label) {
// only add one baseLayer
if (!baseLayerAdded) {
tileLayer.addTo(map);
baseLayerAdded = true;
}
baseLayers[tile.label] = tileLayer;
} else {
// add all tiles without labels into the map
tileLayer.addTo(map);
}
}
// add layer control when there are more than two layers
if (tiles.length > 1) {
const layerControlOpts = leafletModel.get('layerControl');
L.control.layers(baseLayers, {}, layerControlOpts).addTo(map);
}
/*
Encapsulate viewportRoot element into
the parent element responsible for moving,
avoiding direct manipulation of viewportRoot elements
affecting related attributes such as offset.
*/
let moveContainer = document.createElement('div');
moveContainer.style = 'position: relative;';
moveContainer.appendChild(viewportRoot);
new CustomOverlay(moveContainer).addTo(map);
}
let map = leafletModel.__map;
// Set leaflet options
// centerAndZoom before layout and render
const center = leafletModel.get('center');
const zoom = leafletModel.get('zoom');
if (center && zoom) {
map.setView([center[1], center[0]], zoom);
}
leafletCoordSys = new LeafletCoordSys(map, api);
leafletList.push(leafletCoordSys);
leafletCoordSys.setMapOffset(leafletModel.__mapOffset || [0, 0]);
leafletCoordSys.setZoom(zoom);
leafletCoordSys.setCenter(center);
leafletModel.coordinateSystem = leafletCoordSys;
});
ecModel.eachSeries(function(seriesModel) {
if (seriesModel.get('coordinateSystem') === 'leaflet') {
seriesModel.coordinateSystem = leafletCoordSys;
}
});
return leafletList;
};
export default LeafletCoordSys;