You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
581 lines
16 KiB
581 lines
16 KiB
define([ |
|
"dojo/_base/kernel", |
|
"dojo/_base/declare", |
|
"dojo/_base/lang", |
|
"dojo/_base/array", |
|
"dojo/_base/json", |
|
"dojo/dom", |
|
"dojo/dom-style", |
|
"./_base", |
|
"./TouchInteractionSupport", |
|
"./Layer", |
|
"./Patch" |
|
], function(kernel, declare, lang, array, json, dom, style, openlayers, TouchInteractionSupport, Layer, Patch){ |
|
|
|
kernel.experimental("dojox.geo.openlayers.Map"); |
|
|
|
|
|
Patch.patchGFX(); |
|
|
|
/*===== |
|
dojox.geo.openlayers.__MapArgs = { |
|
// summary: |
|
// The keyword arguments that can be passed in a Map constructor. |
|
// baseLayerType: String |
|
// type of the base layer. Can be any of |
|
// |
|
// - `dojox.geo.openlayers.BaseLayerType.OSM`: Open Street Map base layer |
|
// - `dojox.geo.openlayers.BaseLayerType.Transport`: Open Street Map Transport base layer (opencyclemap.org) |
|
// - `dojox.geo.openlayers.BaseLayerType.WMS`: Web Map Service layer |
|
// - `dojox.geo.openlayers.BaseLayerType.GOOGLE`: Google layer |
|
// - `dojox.geo.openlayers.BaseLayerType.VIRTUAL_EARTH`: Virtual Earth layer |
|
// - `dojox.geo.openlayers.BaseLayerType.BING`: Bing layer |
|
// - `dojox.geo.openlayers.BaseLayerType.YAHOO`: Yahoo layer |
|
// - `dojox.geo.openlayers.BaseLayerType.ARCGIS`: ESRI ArgGIS layer |
|
// baseLayerName: String |
|
// The name of the base layer. |
|
// baseLayerUrl: String |
|
// Some layer may need an url such as Web Map Server. |
|
// baseLayerOptions: String |
|
// Additional specific options passed to OpensLayers layer, such as The list of layer to display, for Web Map Server layer. |
|
}; |
|
=====*/ |
|
|
|
return declare("dojox.geo.openlayers.Map", null, { |
|
// summary: |
|
// A map viewer based on the OpenLayers library. |
|
// |
|
// description: |
|
// The `dojox.geo.openlayers.Map` object allows to view maps from various map providers. |
|
// It encapsulates an `OpenLayers.Map` object on which most operations are delegated. |
|
// GFX layers can be added to display GFX georeferenced shapes as well as Dojo widgets. |
|
// Parameters can be passed as argument at construction time to define the base layer |
|
// type and the base layer parameters such as url or options depending on the type |
|
// specified. These parameters can be any of: |
|
// |
|
// _baseLayerType_: type of the base layer. Can be any of: |
|
// |
|
// - `dojox.geo.openlayers.BaseLayerType.OSM`: Open Street Map base layer |
|
// - `dojox.geo.openlayers.BaseLayerType.Transport`: Open Street Map Transport base layer (opencyclemap.org) |
|
// - `dojox.geo.openlayers.BaseLayerType.WMS`: Web Map Service layer |
|
// - `dojox.geo.openlayers.BaseLayerType.GOOGLE`: Google layer |
|
// - `dojox.geo.openlayers.BaseLayerType.VIRTUAL_EARTH`: Virtual Earth layer |
|
// - `dojox.geo.openlayers.BaseLayerType.BING`: Bing layer |
|
// - `dojox.geo.openlayers.BaseLayerType.YAHOO`: Yahoo layer |
|
// - `dojox.geo.openlayers.BaseLayerType.ARCGIS`: ESRI ArgGIS layer |
|
// |
|
// Note that access to commercial server such as Google, Virtual Earth or Yahoo may need specific licencing. |
|
// |
|
// The parameters value also include: |
|
// |
|
// - `baseLayerName`: The name of the base layer. |
|
// - `baseLayerUrl`: Some layer may need an url such as Web Map Server |
|
// - `baseLayerOptions`: Additional specific options passed to OpensLayers layer, |
|
// such as The list of layer to display, for Web Map Server layer. |
|
// |
|
// example: |
|
// | var map = new dojox.geo.openlayers.widget.Map(div, { |
|
// | baseLayerType: dojox.geo.openlayers.BaseLayerType.OSM, |
|
// | baseLayerName: 'Open Street Map Layer' |
|
// | }); |
|
|
|
// olMap: OpenLayers.Map |
|
// The underlying OpenLayers.Map object. |
|
// Should be accessed on read mode only. |
|
olMap: null, |
|
|
|
_tp: null, |
|
|
|
constructor: function(div, options){ |
|
// summary: |
|
// Constructs a new Map object |
|
if(!options){ |
|
options = {}; |
|
} |
|
|
|
div = dom.byId(div); |
|
|
|
this._tp = { |
|
x: 0, |
|
y: 0 |
|
}; |
|
|
|
var opts = options.openLayersMapOptions; |
|
|
|
if(!opts){ |
|
opts = { |
|
controls: [new OpenLayers.Control.ScaleLine({ |
|
maxWidth: 200 |
|
}), new OpenLayers.Control.Navigation()] |
|
}; |
|
} |
|
if(options.accessible){ |
|
var kbd = new OpenLayers.Control.KeyboardDefaults(); |
|
if(!opts.controls){ |
|
opts.controls = []; |
|
} |
|
opts.controls.push(kbd); |
|
} |
|
var baseLayerType = options.baseLayerType; |
|
if(!baseLayerType){ |
|
baseLayerType = openlayers.BaseLayerType.OSM; |
|
} |
|
var map = new OpenLayers.Map(div, opts); |
|
this.olMap = map; |
|
|
|
this._layerDictionary = { |
|
olLayers: [], |
|
layers: [] |
|
}; |
|
|
|
if(options.touchHandler){ |
|
this._touchControl = new TouchInteractionSupport(map); |
|
} |
|
|
|
var base = this._createBaseLayer(options); |
|
this.addLayer(base); |
|
|
|
this.initialFit(options); |
|
}, |
|
|
|
initialFit: function(params){ |
|
// summary: |
|
// Performs an initial fit to contents. |
|
// tags: |
|
// protected |
|
var o = params.initialLocation; |
|
if(!o){ |
|
o = [-160, 70, 160, -70]; |
|
} |
|
this.fitTo(o); |
|
}, |
|
|
|
setBaseLayerType: function(type){ |
|
// summary: |
|
// Set the base layer type, replacing the existing base layer |
|
// type: dojox/geo/openlayers.BaseLayerType |
|
// base layer type |
|
// returns: |
|
// The newly created layer. |
|
if(type == this.baseLayerType){ |
|
return null; // Layer |
|
} |
|
|
|
var o = null; |
|
if(typeof type == "string"){ |
|
o = { |
|
baseLayerName: type, |
|
baseLayerType: type |
|
}; |
|
this.baseLayerType = type; |
|
}else if(typeof type == "object"){ |
|
o = type; |
|
this.baseLayerType = o.baseLayerType; |
|
} |
|
var bl = null; |
|
if(o != null){ |
|
bl = this._createBaseLayer(o); |
|
if(bl != null){ |
|
var olm = this.olMap; |
|
var ob = olm.getZoom(); |
|
var oc = olm.getCenter(); |
|
var recenter = !!oc && !!olm.baseLayer && !!olm.baseLayer.map; |
|
|
|
if(recenter){ |
|
var proj = olm.getProjectionObject(); |
|
if(proj != null){ |
|
oc = oc.transform(proj, openlayers.EPSG4326); |
|
} |
|
} |
|
var old = olm.baseLayer; |
|
if(old != null){ |
|
var l = this._getLayer(old); |
|
this.removeLayer(l); |
|
} |
|
if(bl != null){ |
|
this.addLayer(bl); |
|
} |
|
if(recenter){ |
|
proj = olm.getProjectionObject(); |
|
if(proj != null){ |
|
oc = oc.transform(openlayers.EPSG4326, proj); |
|
} |
|
olm.setCenter(oc, ob); |
|
} |
|
} |
|
} |
|
return bl; |
|
}, |
|
|
|
getBaseLayerType: function(){ |
|
// summary: |
|
// Returns the base layer type. |
|
// returns: |
|
// The current base layer type. |
|
return this.baseLayerType; // openlayers.BaseLayerType |
|
}, |
|
|
|
getScale: function(geodesic){ |
|
// summary: |
|
// Returns the current scale |
|
// geodesic: Boolean |
|
// Tell if geodesic calculation should be performed. If set to |
|
// true, the scale will be calculated based on the horizontal size of the |
|
// pixel in the center of the map viewport. |
|
var scale = null; |
|
var om = this.olMap; |
|
if(geodesic){ |
|
var units = om.getUnits(); |
|
if(!units){ |
|
return null; // Number |
|
} |
|
var inches = OpenLayers.INCHES_PER_UNIT; |
|
scale = (om.getGeodesicPixelSize().w || 0.000001) * inches["km"] * OpenLayers.DOTS_PER_INCH; |
|
}else{ |
|
scale = om.getScale(); |
|
} |
|
return scale; // Number |
|
}, |
|
|
|
getOLMap: function(){ |
|
// summary: |
|
// gets the underlying OpenLayers map object. |
|
// returns: |
|
// The underlying OpenLayers map object. |
|
return this.olMap; // OpenLayers.Map |
|
}, |
|
|
|
_createBaseLayer: function(params){ |
|
// summary: |
|
// Creates the base layer. |
|
// tags: |
|
// private |
|
var base = null; |
|
var type = params.baseLayerType; |
|
var url = params.baseLayerUrl; |
|
var name = params.baseLayerName; |
|
var options = params.baseLayerOptions; |
|
|
|
if(!name){ |
|
name = type; |
|
} |
|
if(!options){ |
|
options = {}; |
|
} |
|
switch(type){ |
|
case openlayers.BaseLayerType.OSM: |
|
options.transitionEffect = "resize"; |
|
// base = new OpenLayers.Layer.OSM(name, url, options); |
|
base = new Layer(name, { |
|
olLayer: new OpenLayers.Layer.OSM(name, url, options) |
|
}); |
|
break; |
|
case openlayers.BaseLayerType.Transport: |
|
options.transitionEffect = "resize"; |
|
base = new Layer(name, { |
|
olLayer: new OpenLayers.Layer.OSM.TransportMap(name, url, options) |
|
}); |
|
break; |
|
case openlayers.BaseLayerType.WMS: |
|
if(!url){ |
|
url = "http://labs.metacarta.com/wms/vmap0"; |
|
if(!options.layers){ |
|
options.layers = "basic"; |
|
} |
|
} |
|
base = new Layer(name, { |
|
olLayer: new OpenLayers.Layer.WMS(name, url, options, { |
|
transitionEffect: "resize" |
|
}) |
|
}); |
|
break; |
|
case openlayers.BaseLayerType.GOOGLE: |
|
base = new Layer(name, { |
|
olLayer: new OpenLayers.Layer.Google(name, options) |
|
}); |
|
break; |
|
case openlayers.BaseLayerType.VIRTUAL_EARTH: |
|
base = new Layer(name, { |
|
olLayer: new OpenLayers.Layer.VirtualEarth(name, options) |
|
}); |
|
break; |
|
case openlayers.BaseLayerType.YAHOO: |
|
// base = new OpenLayers.Layer.Yahoo(name); |
|
base = new Layer(name, { |
|
olLayer: new OpenLayers.Layer.Yahoo(name, options) |
|
}); |
|
break; |
|
case openlayers.BaseLayerType.ARCGIS: |
|
if(!url){ |
|
url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/export"; |
|
} |
|
base = new Layer(name, { |
|
olLayer: new OpenLayers.Layer.ArcGIS93Rest(name, url, options, {}) |
|
}); |
|
|
|
break; |
|
} |
|
|
|
if(base == null){ |
|
if(type instanceof OpenLayers.Layer){ |
|
base = type; |
|
}else{ |
|
options.transitionEffect = "resize"; |
|
base = new Layer(name, { |
|
olLayer: new OpenLayers.Layer.OSM(name, url, options) |
|
}); |
|
this.baseLayerType = openlayers.BaseLayerType.OSM; |
|
} |
|
} |
|
|
|
return base; |
|
}, |
|
|
|
removeLayer: function(layer){ |
|
// summary: |
|
// Remove the specified layer from the map. |
|
// layer: Layer |
|
// The layer to remove from the map. |
|
var om = this.olMap; |
|
var i = array.indexOf(this._layerDictionary.layers, layer); |
|
if(i > 0){ |
|
this._layerDictionary.layers.splice(i, 1); |
|
} |
|
var oll = layer.olLayer; |
|
var j = array.indexOf(this._layerDictionary.olLayers, oll); |
|
if(j > 0){ |
|
this._layerDictionary.olLayers.splice(i, j); |
|
} |
|
om.removeLayer(oll, false); |
|
}, |
|
|
|
layerIndex: function(layer, index){ |
|
// summary: |
|
// Set or retrieve the layer index. |
|
// description: |
|
// Set or get the layer index, that is the z-order of the layer. |
|
// if the index parameter is provided, the layer index is set to |
|
// this value. If the index parameter is not provided, the index of |
|
// the layer is returned. |
|
// layer: Layer |
|
// the layer to retrieve the index. |
|
// index: int? |
|
// index of the layer |
|
// returns: |
|
// the index of the layer. |
|
var olm = this.olMap; |
|
if(!index){ |
|
return olm.getLayerIndex(layer.olLayer); |
|
} |
|
//olm.raiseLayer(layer.olLayer, index); |
|
olm.setLayerIndex(layer.olLayer, index); |
|
|
|
this._layerDictionary.layers.sort(function(l1, l2){ |
|
return olm.getLayerIndex(l1.olLayer) - olm.getLayerIndex(l2.olLayer); |
|
}); |
|
this._layerDictionary.olLayers.sort(function(l1, l2){ |
|
return olm.getLayerIndex(l1) - olm.getLayerIndex(l2); |
|
}); |
|
|
|
return index; // Number |
|
}, |
|
|
|
addLayer: function(layer){ |
|
// summary: |
|
// Add the specified layer to the map. |
|
// layer: Layer |
|
// The layer to add to the map. |
|
layer.dojoMap = this; |
|
var om = this.olMap; |
|
var ol = layer.olLayer; |
|
this._layerDictionary.olLayers.push(ol); |
|
this._layerDictionary.layers.push(layer); |
|
om.addLayer(ol); |
|
layer.added(); |
|
}, |
|
|
|
_getLayer: function(/*OpenLayer.Layer */ol){ |
|
// summary: |
|
// Retrieve the dojox.geo.openlayer.Layer from the OpenLayer.Layer |
|
// tags: |
|
// private |
|
var i = array.indexOf(this._layerDictionary.olLayers, ol); |
|
if(i != -1){ |
|
return this._layerDictionary.layers[i]; |
|
} |
|
return null; |
|
}, |
|
|
|
getLayer: function(property, value){ |
|
// summary: |
|
// Returns the layer whose property matches the value. |
|
// property: String |
|
// The property to check |
|
// value: Object |
|
// The value to match |
|
// returns: |
|
// The layer(s) matching the property's value. Since multiple layers |
|
// match the property's value the return value is an array. |
|
// example: |
|
// var layers = map.getLayer("name", "Layer Name"); |
|
var om = this.olMap; |
|
var ols = om.getBy("layers", property, value); |
|
var ret = new Array(); //[]; |
|
array.forEach(ols, function(ol){ |
|
ret.push(this._getLayer(ol)); |
|
}, this); |
|
return ret; // Layer[] |
|
}, |
|
|
|
getLayerCount: function(){ |
|
// summary: |
|
// Returns the count of layers of this map. |
|
// returns: |
|
// The number of layers of this map. |
|
var om = this.olMap; |
|
if(om.layers == null){ |
|
return 0; |
|
} |
|
return om.layers.length; // Number |
|
}, |
|
|
|
fitTo: function(o){ |
|
// summary: |
|
// Fits the map on a point,or an area |
|
// description: |
|
// Fits the map on the point or extent specified as parameter. |
|
// o: Object |
|
// Object with key values fit parameters or a JSON string. |
|
// example: |
|
// Examples of arguments passed to the fitTo function: |
|
// | null |
|
// The map is fit on full extent |
|
// |
|
// | { |
|
// | bounds: [ulx, uly, lrx, lry] |
|
// | } |
|
// The map is fit on the specified bounds expressed as decimal degrees latitude and longitude. |
|
// The bounds are defined with their upper left and lower right corners coordinates. |
|
// |
|
// | { |
|
// | position: [longitude, latitude], |
|
// | extent: degrees |
|
// | } |
|
// The map is fit on the specified position showing the extent `<extent>` around |
|
// the specified center position. |
|
|
|
var map = this.olMap; |
|
var from = openlayers.EPSG4326; |
|
|
|
if(o == null){ |
|
var c = this.transformXY(0, 0, from); |
|
map.setCenter(new OpenLayers.LonLat(c.x, c.y)); |
|
return; |
|
} |
|
var b = null; |
|
if(typeof o == "string"){ |
|
var j = json.fromJson(o); |
|
}else{ |
|
j = o; |
|
} |
|
var ul; |
|
var lr; |
|
if(j.hasOwnProperty("bounds")){ |
|
var a = j.bounds; |
|
b = new OpenLayers.Bounds(); |
|
ul = this.transformXY(a[0], a[1], from); |
|
b.left = ul.x; |
|
b.top = ul.y; |
|
lr = this.transformXY(a[2], a[3], from); |
|
b.right = lr.x; |
|
b.bottom = lr.y; |
|
} |
|
if(b == null){ |
|
if(j.hasOwnProperty("position")){ |
|
var p = j.position; |
|
var e = j.hasOwnProperty("extent") ? j.extent : 1; |
|
if(typeof e == "string"){ |
|
e = parseFloat(e); |
|
} |
|
b = new OpenLayers.Bounds(); |
|
ul = this.transformXY(p[0] - e, p[1] + e, from); |
|
b.left = ul.x; |
|
b.top = ul.y; |
|
lr = this.transformXY(p[0] + e, p[1] - e, from); |
|
b.right = lr.x; |
|
b.bottom = lr.y; |
|
} |
|
} |
|
if(b == null){ |
|
if(o.length == 4){ |
|
b = new OpenLayers.Bounds(); |
|
// TODO Choose the correct method |
|
if(false){ |
|
b.left = o[0]; |
|
b.top = o[1]; |
|
|
|
b.right = o[2]; |
|
b.bottom = o[3]; |
|
}else{ |
|
ul = this.transformXY(o[0], o[1], from); |
|
b.left = ul.x; |
|
b.top = ul.y; |
|
lr = this.transformXY(o[2], o[3], from); |
|
b.right = lr.x; |
|
b.bottom = lr.y; |
|
} |
|
} |
|
} |
|
if(b != null){ |
|
map.zoomToExtent(b, true); |
|
} |
|
}, |
|
|
|
transform: function(p, from, to){ |
|
// summary: |
|
// Transforms the point passed as argument, expressed in the <em>from</em> |
|
// coordinate system to the map coordinate system. |
|
// description: |
|
// Transforms the point passed as argument without modifying it. The point is supposed to be expressed |
|
// in the <em>from</em> coordinate system and is transformed to the map coordinate system. |
|
// p: Object {x, y} |
|
// The point to transform |
|
// from: OpenLayers.Projection |
|
// The projection in which the point is expressed. |
|
return this.transformXY(p.x, p.y, from, to); |
|
}, |
|
|
|
transformXY: function(x, y, from, to){ |
|
// summary: |
|
// Transforms the coordinates passed as argument, expressed in the <em>from</em> |
|
// coordinate system to the map coordinate system. |
|
// description: |
|
// Transforms the coordinates passed as argument. The coordinate are supposed to be expressed |
|
// in the <em>from</em> coordinate system and are transformed to the map coordinate system. |
|
// x: Number |
|
// The longitude coordinate to transform. |
|
// y: Number |
|
// The latitude coordinate to transform. |
|
// from: OpenLayers.Projection? |
|
// The projection in which the point is expressed, or EPSG4326 is not specified. |
|
// to: OpenLayers.Projection? |
|
// The projection in which the point is converted to. In not specifed, the map projection is used. |
|
// returns: |
|
// The transformed coordinate as an {x,y} Object. |
|
|
|
var tp = this._tp; |
|
tp.x = x; |
|
tp.y = y; |
|
if(!from){ |
|
from = openlayers.EPSG4326; |
|
} |
|
if(!to){ |
|
to = this.olMap.getProjectionObject(); |
|
} |
|
tp = OpenLayers.Projection.transform(tp, from, to); |
|
return tp; // Object |
|
} |
|
|
|
}); |
|
|
|
});
|
|
|