leaflet-curve
Version:
A Leaflet plugin for drawing Bézier curves and other complex shapes.
195 lines (168 loc) • 5.16 kB
JavaScript
/*
* Leaflet.curve v0.1.0 - a plugin for Leaflet mapping library. https://github.com/elfalem/Leaflet.curve
* (c) elfalem 2015
*/
/*
* note that SVG (x, y) corresponds to (long, lat)
*/
L.Curve = L.Path.extend({
options: {
},
initialize: function(path, options){
L.setOptions(this, options);
this._setPath(path);
},
getPath: function(){
return this._coords;
},
setPath: function(path){
this._setPath(path);
return this.redraw();
},
getBounds: function() {
return this._bounds;
},
_setPath: function(path){
this._coords = path;
this._bounds = this._computeBounds();
},
_computeBounds: function(){
var bound = new L.LatLngBounds();
var lastPoint;
var lastCommand;
for(var i = 0; i < this._coords.length; i++){
coord = this._coords[i];
if(typeof coord == 'string' || coord instanceof String){
lastCommand = coord;
}else if(lastCommand == 'H'){
bound.extend([lastPoint.lat,coord[0]]);
lastPoint = new L.latLng(lastPoint.lat,coord[0]);
}else if(lastCommand == 'V'){
bound.extend([coord[0], lastPoint.lng]);
lastPoint = new L.latLng(coord[0], lastPoint.lng);
}else if(lastCommand == 'C'){
var controlPoint1 = new L.latLng(coord[0], coord[1]);
coord = this._coords[++i];
var controlPoint2 = new L.latLng(coord[0], coord[1]);
coord = this._coords[++i];
var endPoint = new L.latLng(coord[0], coord[1]);
bound.extend(controlPoint1);
bound.extend(controlPoint2);
bound.extend(endPoint);
endPoint.controlPoint1 = controlPoint1;
endPoint.controlPoint2 = controlPoint2;
lastPoint = endPoint;
}else if(lastCommand == 'S'){
var controlPoint2 = new L.latLng(coord[0], coord[1]);
coord = this._coords[++i];
var endPoint = new L.latLng(coord[0], coord[1]);
var controlPoint1 = lastPoint;
if(lastPoint.controlPoint2){
var diffLat = lastPoint.lat - lastPoint.controlPoint2.lat;
var diffLng = lastPoint.lng - lastPoint.controlPoint2.lng;
controlPoint1 = new L.latLng(lastPoint.lat + diffLat, lastPoint.lng + diffLng);
}
bound.extend(controlPoint1);
bound.extend(controlPoint2);
bound.extend(endPoint);
endPoint.controlPoint1 = controlPoint1;
endPoint.controlPoint2 = controlPoint2;
lastPoint = endPoint;
}else if(lastCommand == 'Q'){
var controlPoint = new L.latLng(coord[0], coord[1]);
coord = this._coords[++i];
var endPoint = new L.latLng(coord[0], coord[1]);
bound.extend(controlPoint);
bound.extend(endPoint);
endPoint.controlPoint = controlPoint;
lastPoint = endPoint;
}else if(lastCommand == 'T'){
var endPoint = new L.latLng(coord[0], coord[1]);
var controlPoint = lastPoint;
if(lastPoint.controlPoint){
var diffLat = lastPoint.lat - lastPoint.controlPoint.lat;
var diffLng = lastPoint.lng - lastPoint.controlPoint.lng;
controlPoint = new L.latLng(lastPoint.lat + diffLat, lastPoint.lng + diffLng);
}
bound.extend(controlPoint);
bound.extend(endPoint);
endPoint.controlPoint = controlPoint;
lastPoint = endPoint;
}else{
bound.extend(coord);
lastPoint = new L.latLng(coord[0], coord[1]);
}
}
return bound;
},
//TODO: use a centroid algorithm instead
getCenter: function () {
return this._bounds.getCenter();
},
_update: function(){
if (!this._map) { return; }
this._updatePath();
},
_updatePath: function() {
this._renderer._updatecurve(this);
},
_project: function() {
var coord, lastCoord, curCommand, curPoint;
this._points = [];
for(var i = 0; i < this._coords.length; i++){
coord = this._coords[i];
if(typeof coord == 'string' || coord instanceof String){
this._points.push(coord);
curCommand = coord;
}else {
switch(coord.length){
case 2:
curPoint = this._map.latLngToLayerPoint(coord);
lastCoord = coord;
break;
case 1:
if(curCommand == 'H'){
curPoint = this._map.latLngToLayerPoint([lastCoord[0], coord[0]]);
lastCoord = [lastCoord[0], coord[0]];
}else{
curPoint = this._map.latLngToLayerPoint([coord[0], lastCoord[1]]);
lastCoord = [coord[0], lastCoord[1]];
}
break;
}
this._points.push(curPoint);
}
}
}
});
L.curve = function (path, options){
return new L.Curve(path, options);
};
L.SVG.include({
_updatecurve: function(layer){
this._setPath(layer, this._curvePointsToPath(layer._points));
},
_curvePointsToPath: function(points){
var point, curCommand, str = '';
for(var i = 0; i < points.length; i++){
point = points[i];
if(typeof point == 'string' || point instanceof String){
curCommand = point;
str += curCommand;
}else{
switch(curCommand){
case 'H':
str += point.x + ' ';
break;
case 'V':
str += point.y + ' ';
break;
default:
str += point.x + ',' + point.y + ' ';
break;
}
}
}
return str || 'M0 0';
}
});