mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-16 13:59:27 +02:00
Reformat map, starting to work on removing uis
This commit is contained in:
+117
-116
@@ -8,126 +8,127 @@
|
||||
// opacity
|
||||
|
||||
define(['dojo/_base/declare','iD/Entity','iD/renderer/Map'],
|
||||
function(declare) {
|
||||
function(declare) {
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// EntityUI base class
|
||||
// ----------------------------------------------------------------------
|
||||
// EntityUI base class
|
||||
|
||||
declare("iD.renderer.EntityUI", null, {
|
||||
declare("iD.renderer.EntityUI", null, {
|
||||
|
||||
entity:null, // Entity this represents
|
||||
map:null, // the Map object containing this
|
||||
layer:0, // OSM layer
|
||||
sprites:null, // array of sprites created for this EntityUI
|
||||
styleList:null, // current StyleList
|
||||
stateClasses:null, // list of stateClass tags to apply
|
||||
entity:null, // Entity this represents
|
||||
map:null, // the Map object containing this
|
||||
layer:0, // OSM layer
|
||||
sprites:null, // array of sprites created for this EntityUI
|
||||
styleList:null, // current StyleList
|
||||
stateClasses:null, // list of stateClass tags to apply
|
||||
|
||||
constructor:function(entity,map,stateClasses) {
|
||||
// summary: Base class for a UI representing an entity.
|
||||
this.entity=entity;
|
||||
this.map=map;
|
||||
this.stateClasses=stateClasses ? stateClasses.slice() : [];
|
||||
this.sprites=[];
|
||||
},
|
||||
getConnection:function() {
|
||||
// summary: Get the Connection from where the map draws its data.
|
||||
return this.map.connection; // iD.Connection
|
||||
},
|
||||
targetGroup:function(groupType,sublayer) {
|
||||
// summary: Find a gfx.Group to render on.
|
||||
return this.map.sublayer(this.layer,groupType,sublayer); // dojox.gfx.Group
|
||||
},
|
||||
recordSprite:function(sprite) {
|
||||
// summary: Record that an individual sprite (one stroke, icon or text item) has been added.
|
||||
if (!_.include(this.sprites, sprite)) {
|
||||
this.sprites.push(sprite);
|
||||
constructor: function(entity,map,stateClasses) {
|
||||
// summary: Base class for a UI representing an entity.
|
||||
this.entity=entity;
|
||||
this.map=map;
|
||||
this.stateClasses=stateClasses ? stateClasses.slice() : [];
|
||||
this.sprites=[];
|
||||
},
|
||||
getConnection: function() {
|
||||
// summary: Get the Connection from where the map draws its data.
|
||||
return this.map.connection; // iD.Connection
|
||||
},
|
||||
targetGroup: function(groupType,sublayer) {
|
||||
// summary: Find a gfx.Group to render on.
|
||||
return this.map.sublayer(this.layer,groupType,sublayer); // dojox.gfx.Group
|
||||
},
|
||||
recordSprite: function(sprite) {
|
||||
// summary: Record that an individual sprite (one stroke, icon or text item) has been added.
|
||||
if (!_.include(this.sprites, sprite)) {
|
||||
this.sprites.push(sprite);
|
||||
}
|
||||
return sprite;
|
||||
},
|
||||
removeSprites: function() {
|
||||
// summary: Clear all sprites currently used.
|
||||
for (var i=0; i<this.sprites.length; i++) {
|
||||
this.sprites[i].removeShape();
|
||||
}
|
||||
this.sprites=[];
|
||||
},
|
||||
refreshStyleList: function(tags) {
|
||||
// summary: Calculate the list of styles that apply to this UI at this zoom level.
|
||||
if (!this.styleList || !this.styleList.isValidAt(this.map.zoom)) {
|
||||
this.styleList=this.map.ruleset.getStyles(this.entity,tags, this.map.zoom);
|
||||
}
|
||||
this.layer=this.styleList.layerOverride();
|
||||
if (isNaN(this.layer)) {
|
||||
this.layer=0;
|
||||
if (tags.layer) { this.layer = +tags.layer; }
|
||||
}
|
||||
|
||||
// Iterate through each subpart, drawing any styles on that layer
|
||||
var drawn=false;
|
||||
for (i=0; i<this.styleList.subparts.length; i++) {
|
||||
var subpart=this.styleList.subparts[i];
|
||||
}
|
||||
},
|
||||
getEnhancedTags: function() {
|
||||
// summary: Return tags for this entity augmented by the EntityUI's state classes.
|
||||
var tags = _.clone(this.entity.tags);
|
||||
// Apply stateClasses (hover, selected, hoverway, selectedway)
|
||||
for (var i in this.stateClasses) {
|
||||
tags[':'+this.stateClasses[i]] = 'yes';
|
||||
}
|
||||
// todo - Add any common 'special-case' tags, e.g. :hasTags
|
||||
return tags; // Object
|
||||
},
|
||||
|
||||
// --------------------
|
||||
// State class handling
|
||||
|
||||
setStateClasses:function(stateClasses) {
|
||||
// summary: Set all state classes at once, and prompt a redraw if they're different to previously,
|
||||
if (stateClasses && this.stateClasses.join(',')!=stateClasses.join(',')) {
|
||||
this.stateClasses=stateClasses.slice();
|
||||
this.invalidateStyleList();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setStateClass:function(sc) {
|
||||
// summary: Set a single state class, and prompt a redraw if it wasn't set previously.
|
||||
if (this.stateClasses.indexOf(sc)==-1) {
|
||||
this.stateClasses.push(sc);
|
||||
this.invalidateStyleList();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
resetStateClass:function(sc) {
|
||||
// summary: Reset a single state class, and prompt a redraw if it was set previously.
|
||||
if (this.stateClasses.indexOf(sc)>-1) {
|
||||
this.stateClasses.splice(this.stateClasses.indexOf(sc),1);
|
||||
this.invalidateStyleList();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
hasStateClass:function(sc) {
|
||||
// summary: Is a particular state class set for this UI?
|
||||
return this.stateClasses.indexOf(sc) > -1;
|
||||
},
|
||||
|
||||
invalidateStyleList:function() {
|
||||
// summary: Invalidate the StyleList so it's recalculated on next redraw.
|
||||
this.styleList = null;
|
||||
},
|
||||
|
||||
// --------------------
|
||||
// Mouse event handling
|
||||
|
||||
entityMouseEvent:function(event) {
|
||||
// summary: Receive a mouse event (e.g. clicking on the UI), and forward it to the Controller.
|
||||
this.map.controller.entityMouseEvent(event, event.gfxTarget.source);
|
||||
event.stopPropagation();
|
||||
}
|
||||
return sprite;
|
||||
},
|
||||
removeSprites:function() {
|
||||
// summary: Clear all sprites currently used.
|
||||
for (var i=0; i<this.sprites.length; i++) {
|
||||
this.sprites[i].removeShape();
|
||||
}
|
||||
this.sprites=[];
|
||||
},
|
||||
refreshStyleList:function(tags) {
|
||||
// summary: Calculate the list of styles that apply to this UI at this zoom level.
|
||||
if (!this.styleList || !this.styleList.isValidAt(this.map.zoom)) {
|
||||
this.styleList=this.map.ruleset.getStyles(this.entity,tags, this.map.zoom);
|
||||
}
|
||||
this.layer=this.styleList.layerOverride();
|
||||
if (isNaN(this.layer)) {
|
||||
this.layer=0;
|
||||
if (tags.layer) { this.layer = +tags.layer; }
|
||||
}
|
||||
});
|
||||
|
||||
// Iterate through each subpart, drawing any styles on that layer
|
||||
var drawn=false;
|
||||
for (i=0; i<this.styleList.subparts.length; i++) {
|
||||
var subpart=this.styleList.subparts[i];
|
||||
}
|
||||
},
|
||||
getEnhancedTags:function() {
|
||||
// summary: Return tags for this entity augmented by the EntityUI's state classes.
|
||||
var tags = _.clone(this.entity.tags);
|
||||
// Apply stateClasses (hover, selected, hoverway, selectedway)
|
||||
for (var i in this.stateClasses) {
|
||||
tags[':'+this.stateClasses[i]] = 'yes';
|
||||
}
|
||||
// todo - Add any common 'special-case' tags, e.g. :hasTags
|
||||
return tags; // Object
|
||||
},
|
||||
|
||||
// --------------------
|
||||
// State class handling
|
||||
|
||||
setStateClasses:function(stateClasses) {
|
||||
// summary: Set all state classes at once, and prompt a redraw if they're different to previously,
|
||||
if (stateClasses && this.stateClasses.join(',')!=stateClasses.join(',')) {
|
||||
this.stateClasses=stateClasses.slice();
|
||||
this.invalidateStyleList();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setStateClass:function(sc) {
|
||||
// summary: Set a single state class, and prompt a redraw if it wasn't set previously.
|
||||
if (this.stateClasses.indexOf(sc)==-1) {
|
||||
this.stateClasses.push(sc);
|
||||
this.invalidateStyleList();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
resetStateClass:function(sc) {
|
||||
// summary: Reset a single state class, and prompt a redraw if it was set previously.
|
||||
if (this.stateClasses.indexOf(sc)>-1) {
|
||||
this.stateClasses.splice(this.stateClasses.indexOf(sc),1);
|
||||
this.invalidateStyleList();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
hasStateClass:function(sc) {
|
||||
// summary: Is a particular state class set for this UI?
|
||||
return this.stateClasses.indexOf(sc)>-1;
|
||||
},
|
||||
invalidateStyleList:function() {
|
||||
// summary: Invalidate the StyleList so it's recalculated on next redraw.
|
||||
this.styleList=null;
|
||||
},
|
||||
|
||||
// --------------------
|
||||
// Mouse event handling
|
||||
|
||||
entityMouseEvent:function(event) {
|
||||
// summary: Receive a mouse event (e.g. clicking on the UI), and forward it to the Controller.
|
||||
this.map.controller.entityMouseEvent(event, event.gfxTarget.source);
|
||||
event.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// End of module
|
||||
// ----------------------------------------------------------------------
|
||||
// End of module
|
||||
});
|
||||
|
||||
+439
-434
@@ -2,295 +2,300 @@
|
||||
// at present this combines P2's Map and MapPaint functionality
|
||||
|
||||
define(['dojo/_base/declare','dojo/_base/event',
|
||||
'dojo/dom-geometry',
|
||||
'dojox/gfx','dojox/gfx/matrix',
|
||||
'iD/Connection','iD/Entity','iD/renderer/EntityUI','iD/renderer/WayUI','iD/renderer/NodeUI'],
|
||||
function(declare, Event, domGeom, Gfx, Matrix){
|
||||
'dojo/dom-geometry',
|
||||
'dojox/gfx','dojox/gfx/matrix',
|
||||
'iD/Connection','iD/Entity','iD/renderer/EntityUI','iD/renderer/WayUI','iD/renderer/NodeUI'],
|
||||
function(declare, Event, domGeom, Gfx, Matrix){
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Connection base class
|
||||
// ----------------------------------------------------------------------
|
||||
// Connection base class
|
||||
|
||||
declare("iD.renderer.Map", null, {
|
||||
declare("iD.renderer.Map", null, {
|
||||
|
||||
MASTERSCALE: 5825.4222222222,
|
||||
MINSCALE: 14,
|
||||
MAXSCALE: 23,
|
||||
zoom: NaN,
|
||||
zoomfactor: NaN,
|
||||
baselon: NaN, // original longitude at top left of viewport
|
||||
baselat: NaN, // original latitude at top left of viewport
|
||||
baselatp: NaN, // original projected latitude at top left of viewport
|
||||
MASTERSCALE: 5825.4222222222,
|
||||
MINSCALE: 14,
|
||||
MAXSCALE: 23,
|
||||
zoom: NaN,
|
||||
zoomfactor: NaN,
|
||||
baselon: NaN, // original longitude at top left of viewport
|
||||
baselat: NaN, // original latitude at top left of viewport
|
||||
baselatp: NaN, // original projected latitude at top left of viewport
|
||||
|
||||
div: '', // <div> of this map
|
||||
surface: null, // <div>.surface containing the rendering
|
||||
container: null, // root-level group within the surface
|
||||
backdrop: null, // coloured backdrop (MapCSS canvas element)
|
||||
connection: null, // data store
|
||||
controller: null, // UI controller
|
||||
uis: {},
|
||||
div: '', // <div> of this map
|
||||
surface: null, // <div>.surface containing the rendering
|
||||
container: null, // root-level group within the surface
|
||||
backdrop: null, // coloured backdrop (MapCSS canvas element)
|
||||
connection: null, // data store
|
||||
controller: null, // UI controller
|
||||
uis: {},
|
||||
|
||||
tilegroup: null, // group within container for adding bitmap tiles
|
||||
tiles: {}, // index of tile objects
|
||||
tilebaseURL: 'http://ecn.t0.tiles.virtualearth.net/tiles/a$quadkey.jpeg?g=587&mkt=en-gb&n=z', // Bing imagery URL
|
||||
tilegroup: null, // group within container for adding bitmap tiles
|
||||
tiles: {}, // index of tile objects
|
||||
tilebaseURL: 'http://ecn.t0.tiles.virtualearth.net/tiles/a$quadkey.jpeg?g=587&mkt=en-gb&n=z', // Bing imagery URL
|
||||
|
||||
dragging: false, // current drag state
|
||||
dragged: false, // was most recent click a drag?
|
||||
dragx: NaN, // click co-ordinates at previously recorded drag event
|
||||
dragy: NaN, // |
|
||||
startdragx: NaN, // click co-ordinates at start of drag
|
||||
startdragy: NaN, // |
|
||||
dragtime: NaN, // timestamp of mouseup (compared to stop resulting click from firing)
|
||||
dragconnect: null, // event listener for endDrag
|
||||
dragging: false, // current drag state
|
||||
dragged: false, // was most recent click a drag?
|
||||
dragx: NaN, // click co-ordinates at previously recorded drag event
|
||||
dragy: NaN, // |
|
||||
startdragx: NaN, // click co-ordinates at start of drag
|
||||
startdragy: NaN, // |
|
||||
dragtime: NaN, // timestamp of mouseup (compared to stop resulting click from firing)
|
||||
dragconnect: null, // event listener for endDrag
|
||||
|
||||
containerx: 0, // screen co-ordinates of container
|
||||
containery: 0, // |
|
||||
centrelat: NaN, // lat/long and bounding box of map
|
||||
centrelon: NaN, // |
|
||||
extent: {}, // |
|
||||
mapheight: NaN, // size of map object in pixels
|
||||
mapwidth: NaN, // |
|
||||
containerx: 0, // screen co-ordinates of container
|
||||
containery: 0, // |
|
||||
centrelat: NaN, // lat/long and bounding box of map
|
||||
centrelon: NaN, // |
|
||||
extent: {}, // |
|
||||
mapheight: NaN, // size of map object in pixels
|
||||
mapwidth: NaN, // |
|
||||
|
||||
layers: null, // array-like object of Groups, one for each OSM layer
|
||||
minlayer: -5, // minimum OSM layer supported
|
||||
maxlayer: 5, // maximum OSM layer supported
|
||||
layers: null, // array-like object of Groups, one for each OSM layer
|
||||
minlayer: -5, // minimum OSM layer supported
|
||||
maxlayer: 5, // maximum OSM layer supported
|
||||
|
||||
elastic: null, // Group for drawing elastic band
|
||||
elastic: null, // Group for drawing elastic band
|
||||
|
||||
ruleset: null, // map style
|
||||
ruleset: null, // map style
|
||||
|
||||
constructor: function(obj) {
|
||||
// summary: The main map display, containing the individual sprites (UIs) for each entity.
|
||||
// obj: Object An object containing .lat, .lon, .scale, .div (the name of the <div> to be used),
|
||||
// .connection, .width (px) and .height (px) properties.
|
||||
constructor: function(obj) {
|
||||
// summary: The main map display, containing the individual sprites (UIs) for each entity.
|
||||
// obj: Object An object containing .lat, .lon, .scale, .div (the name of the <div> to be used),
|
||||
// .connection, .width (px) and .height (px) properties.
|
||||
|
||||
this.mapwidth = obj.width ? obj.width : 800;
|
||||
this.mapheight = obj.height ? obj.height : 400;
|
||||
this.mapwidth = obj.width ? obj.width : 800;
|
||||
this.mapheight = obj.height ? obj.height : 400;
|
||||
|
||||
// Initialise variables
|
||||
this.uis = {};
|
||||
this.div=document.getElementById(obj.div);
|
||||
this.surface=Gfx.createSurface(obj.div, this.mapwidth, this.mapheight);
|
||||
this.backdrop=this.surface.createRect({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.mapwidth,
|
||||
height: this.mapheight
|
||||
}).setFill(new dojo.Color([255,255,245,1]));
|
||||
this.tilegroup = this.surface.createGroup();
|
||||
this.container = this.surface.createGroup();
|
||||
this.connection = obj.connection;
|
||||
this.zoom = obj.zoom ? obj.zoom : 17;
|
||||
this.baselon = obj.lon;
|
||||
this.baselat = obj.lat;
|
||||
this.baselatp = this.lat2latp(obj.lat);
|
||||
this._setScaleFactor();
|
||||
this.updateCoordsFromViewportPosition();
|
||||
// Initialise variables
|
||||
this.uis = {};
|
||||
this.div=document.getElementById(obj.div);
|
||||
this.surface=Gfx.createSurface(obj.div, this.mapwidth, this.mapheight);
|
||||
this.backdrop=this.surface.createRect({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.mapwidth,
|
||||
height: this.mapheight
|
||||
}).setFill(new dojo.Color([255,255,245,1]));
|
||||
this.tilegroup = this.surface.createGroup();
|
||||
this.container = this.surface.createGroup();
|
||||
this.connection = obj.connection;
|
||||
this.zoom = obj.zoom ? obj.zoom : 17;
|
||||
this.baselon = obj.lon;
|
||||
this.baselat = obj.lat;
|
||||
this.baselatp = this.lat2latp(obj.lat);
|
||||
this._setScaleFactor();
|
||||
this.updateCoordsFromViewportPosition();
|
||||
|
||||
// Cache the margin box, since this is expensive.
|
||||
this.marginBox = domGeom.getMarginBox(this.div);
|
||||
// Cache the margin box, since this is expensive.
|
||||
this.marginBox = domGeom.getMarginBox(this.div);
|
||||
|
||||
// Initialise layers
|
||||
this.layers={};
|
||||
for (var l=this.minlayer; l<=this.maxlayer; l++) {
|
||||
var r=this.container.createGroup();
|
||||
this.layers[l]={
|
||||
root: r,
|
||||
fill: r.createGroup(),
|
||||
casing: r.createGroup(),
|
||||
stroke: r.createGroup(),
|
||||
text: r.createGroup(),
|
||||
hit: r.createGroup()
|
||||
};
|
||||
}
|
||||
|
||||
// Create group for elastic band
|
||||
this.elastic = this.container.createGroup();
|
||||
|
||||
// Make draggable
|
||||
this.backdrop.connect("onmousedown", _.bind(this.startDrag, this));
|
||||
this.tilegroup.connect("onmousedown", _.bind(this.startDrag, this));
|
||||
this.surface.connect("onclick", _.bind(this.clickSurface, this));
|
||||
this.surface.connect("onmousemove", _.bind(this.processMove, this));
|
||||
this.surface.connect("onmousedown", _.bind(this._mouseEvent, this));
|
||||
this.surface.connect("onmouseup", _.bind(this._mouseEvent, this));
|
||||
},
|
||||
|
||||
setController:function(controller) {
|
||||
// summary: Set the controller that will handle events on the map (e.g. mouse clicks).
|
||||
this.controller = controller;
|
||||
},
|
||||
|
||||
_moveToPosition:function(group, position) {
|
||||
// summary: Supplementary method for dojox.gfx.
|
||||
// This should ideally be core Dojo stuff: see http://bugs.dojotoolkit.org/ticket/15296
|
||||
var parent=group.getParent();
|
||||
if (!parent) { return; }
|
||||
this._moveChildToPosition(parent,group,position);
|
||||
if (position === group.rawNode.parentNode.childNodes.length) {
|
||||
group.rawNode.parentNode.appendChild(group.rawNode);
|
||||
} else {
|
||||
group.rawNode.parentNode.insertBefore(group.rawNode, group.rawNode.parentNode.childNodes[position]);
|
||||
}
|
||||
},
|
||||
|
||||
_moveChildToPosition: function(parent, child, position) {
|
||||
for (var i = 0; i < parent.children.length; ++i){
|
||||
if (parent.children[i] === child){
|
||||
parent.children.splice(i, 1);
|
||||
parent.children.splice(position, 0, child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// ----------------------------
|
||||
// Sprite and EntityUI handling
|
||||
|
||||
sublayer:function(layer,groupType,sublayer) {
|
||||
// summary: Find the gfx.Group for a given OSM layer and rendering sublayer, creating it
|
||||
// if necessary. Note that sublayers are only implemented for stroke and fill.
|
||||
// groupType: String 'casing','text','hit','stroke', or 'fill'
|
||||
var collection = this.layers[layer][groupType], sub;
|
||||
switch (groupType) {
|
||||
case 'casing':
|
||||
case 'text':
|
||||
case 'hit':
|
||||
return collection;
|
||||
}
|
||||
// Find correct sublayer, inserting if necessary
|
||||
var insertAt=collection.children.length;
|
||||
for (var i = 0; i < collection.children.length; i++) {
|
||||
sub=collection.children[i];
|
||||
if (sub.sublayer==sublayer) { return sub; }
|
||||
else if (sub.sublayer>sublayer) {
|
||||
sub = collection.createGroup();
|
||||
this._moveToPosition(sub,i);
|
||||
sub.sublayer=sublayer;
|
||||
return sub;
|
||||
}
|
||||
}
|
||||
sub = collection.createGroup().moveToFront();
|
||||
sub.sublayer=sublayer;
|
||||
return sub; // dojox.gfx.Group
|
||||
},
|
||||
|
||||
createUI: function(e, stateClasses) {
|
||||
// summary: Create a UI (sprite) for an entity, assigning any specified state classes
|
||||
// (temporary attributes such as ':hover' or ':selected')
|
||||
if (!this.uis[e.id]) {
|
||||
if (e.entityType === 'node') {
|
||||
this.uis[e.id] = new iD.renderer.NodeUI(e, this, stateClasses);
|
||||
} else if (e.entityType === 'way') {
|
||||
this.uis[e.id] = new iD.renderer.WayUI(e, this, stateClasses);
|
||||
// Initialise layers
|
||||
this.layers={};
|
||||
for (var l=this.minlayer; l<=this.maxlayer; l++) {
|
||||
var r=this.container.createGroup();
|
||||
this.layers[l]={
|
||||
root: r,
|
||||
fill: r.createGroup(),
|
||||
casing: r.createGroup(),
|
||||
stroke: r.createGroup(),
|
||||
text: r.createGroup(),
|
||||
hit: r.createGroup()
|
||||
};
|
||||
}
|
||||
} else {
|
||||
this.uis[e.id].setStateClasses(stateClasses).redraw();
|
||||
}
|
||||
},
|
||||
|
||||
getUI: function(e) {
|
||||
// summary: Return the UI for an entity, if it exists.
|
||||
return this.uis[e.id]; // iD.renderer.EntityUI
|
||||
},
|
||||
// Create group for elastic band
|
||||
this.elastic = this.container.createGroup();
|
||||
|
||||
refreshUI: function(e) {
|
||||
// summary: Redraw the UI for an entity.
|
||||
if (this.uis[e.id]) { this.uis[e.id].redraw(); }
|
||||
},
|
||||
// Make draggable
|
||||
this.backdrop.connect("onmousedown", _.bind(this.startDrag, this));
|
||||
this.tilegroup.connect("onmousedown", _.bind(this.startDrag, this));
|
||||
this.surface.connect("onclick", _.bind(this.clickSurface, this));
|
||||
this.surface.connect("onmousemove", _.bind(this.processMove, this));
|
||||
this.surface.connect("onmousedown", _.bind(this._mouseEvent, this));
|
||||
this.surface.connect("onmouseup", _.bind(this._mouseEvent, this));
|
||||
},
|
||||
|
||||
deleteUI: function(e) {
|
||||
// summary: Delete the UI for an entity.
|
||||
if (this.uis[e.id]) {
|
||||
this.uis[e.id].removeSprites();
|
||||
delete this.uis[e.id];
|
||||
}
|
||||
},
|
||||
setController:function(controller) {
|
||||
// summary: Set the controller that will handle events on the map (e.g. mouse clicks).
|
||||
this.controller = controller;
|
||||
},
|
||||
|
||||
download: function() {
|
||||
// summary: Ask the connection to download data for the current viewport.
|
||||
$('#progress').show().addClass('spinner');
|
||||
this.connection.loadFromAPI(this.extent, _.bind(this.updateUIs, this));
|
||||
},
|
||||
_moveToPosition:function(group, position) {
|
||||
// summary: Supplementary method for dojox.gfx.
|
||||
// This should ideally be core Dojo stuff: see http://bugs.dojotoolkit.org/ticket/15296
|
||||
var parent=group.getParent();
|
||||
if (!parent) { return; }
|
||||
this._moveChildToPosition(parent,group,position);
|
||||
if (position === group.rawNode.parentNode.childNodes.length) {
|
||||
group.rawNode.parentNode.appendChild(group.rawNode);
|
||||
} else {
|
||||
group.rawNode.parentNode.insertBefore(group.rawNode, group.rawNode.parentNode.childNodes[position]);
|
||||
}
|
||||
},
|
||||
|
||||
updateUIs: function() {
|
||||
// summary: Draw/refresh all EntityUIs within the bbox, and remove any others.
|
||||
// redraw: Boolean Should we redraw any UIs that are already present?
|
||||
// remove: Boolean Should we delete any UIs that are no longer in the bbox?
|
||||
$('#progress').hide().removeClass('spinner');
|
||||
var o = this.connection.getObjectsByBbox(this.extent);
|
||||
_(o.inside).chain()
|
||||
.filter(function(w) { return w.loaded; })
|
||||
.each(_.bind(function(e) {
|
||||
if (!this.uis[e.id]) {
|
||||
this.createUI(e);
|
||||
} else {
|
||||
this.uis[e.id].redraw();
|
||||
_moveChildToPosition: function(parent, child, position) {
|
||||
for (var i = 0; i < parent.children.length; ++i){
|
||||
if (parent.children[i] === child){
|
||||
parent.children.splice(i, 1);
|
||||
parent.children.splice(position, 0, child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// ----------------------------
|
||||
// Sprite and EntityUI handling
|
||||
|
||||
sublayer:function(layer,groupType,sublayer) {
|
||||
// summary: Find the gfx.Group for a given OSM layer and rendering sublayer, creating it
|
||||
// if necessary. Note that sublayers are only implemented for stroke and fill.
|
||||
// groupType: String 'casing','text','hit','stroke', or 'fill'
|
||||
var collection = this.layers[layer][groupType], sub;
|
||||
switch (groupType) {
|
||||
case 'casing':
|
||||
case 'text':
|
||||
case 'hit':
|
||||
return collection;
|
||||
}
|
||||
// Find correct sublayer, inserting if necessary
|
||||
var insertAt=collection.children.length;
|
||||
for (var i = 0; i < collection.children.length; i++) {
|
||||
sub=collection.children[i];
|
||||
if (sub.sublayer==sublayer) { return sub; }
|
||||
else if (sub.sublayer>sublayer) {
|
||||
sub = collection.createGroup();
|
||||
this._moveToPosition(sub,i);
|
||||
sub.sublayer=sublayer;
|
||||
return sub;
|
||||
}
|
||||
}
|
||||
sub = collection.createGroup().moveToFront();
|
||||
sub.sublayer=sublayer;
|
||||
return sub; // dojox.gfx.Group
|
||||
},
|
||||
|
||||
createUI: function(e, stateClasses) {
|
||||
// summary: Create a UI (sprite) for an entity, assigning any specified state classes
|
||||
// (temporary attributes such as ':hover' or ':selected')
|
||||
if (!this.uis[e.id]) {
|
||||
if (e.entityType === 'node') {
|
||||
this.uis[e.id] = new iD.renderer.NodeUI(e, this, stateClasses);
|
||||
} else if (e.entityType === 'way') {
|
||||
this.uis[e.id] = new iD.renderer.WayUI(e, this, stateClasses);
|
||||
}
|
||||
} else {
|
||||
this.uis[e.id].setStateClasses(stateClasses).redraw();
|
||||
}
|
||||
},
|
||||
|
||||
getUI: function(e) {
|
||||
// summary: Return the UI for an entity, if it exists.
|
||||
return this.uis[e.id]; // iD.renderer.EntityUI
|
||||
},
|
||||
|
||||
refreshUI: function(e) {
|
||||
// summary: Redraw the UI for an entity.
|
||||
if (this.uis[e.id]) { this.uis[e.id].redraw(); }
|
||||
},
|
||||
|
||||
deleteUI: function(e) {
|
||||
// summary: Delete the UI for an entity.
|
||||
if (this.uis[e.id]) {
|
||||
this.uis[e.id].removeSprites();
|
||||
delete this.uis[e.id];
|
||||
}
|
||||
},
|
||||
|
||||
download: function() {
|
||||
// summary: Ask the connection to download data for the current viewport.
|
||||
$('#progress').show().addClass('spinner');
|
||||
this.connection.loadFromAPI(this.extent, _.bind(this.updateUIs, this));
|
||||
},
|
||||
|
||||
updateUIs: function() {
|
||||
// summary: Draw/refresh all EntityUIs within the bbox, and remove any others.
|
||||
// redraw: Boolean Should we redraw any UIs that are already present?
|
||||
// remove: Boolean Should we delete any UIs that are no longer in the bbox?
|
||||
$('#progress').hide().removeClass('spinner');
|
||||
var o = this.connection.getObjectsByBbox(this.extent);
|
||||
var touch = _(o.inside).chain()
|
||||
.filter(function(w) { return w.loaded; })
|
||||
.map(_.bind(function(e) {
|
||||
if (!this.uis[e.id]) {
|
||||
this.createUI(e);
|
||||
} else {
|
||||
this.uis[e.id].redraw();
|
||||
}
|
||||
return '' + e.id;
|
||||
}, this)).value();
|
||||
_.each(_.difference(_.keys(this.uis), touch), _.bind(function(k) {
|
||||
console.log(k);
|
||||
this.deleteUI(k);
|
||||
}, this));
|
||||
},
|
||||
},
|
||||
|
||||
// -------------
|
||||
// Zoom handling
|
||||
// -------------
|
||||
// Zoom handling
|
||||
|
||||
zoomIn: function() {
|
||||
// summary: Zoom in by one level (unless maximum reached).
|
||||
return this.setZoom(this.zoom + 1);
|
||||
},
|
||||
zoomIn: function() {
|
||||
// summary: Zoom in by one level (unless maximum reached).
|
||||
return this.setZoom(this.zoom + 1);
|
||||
},
|
||||
|
||||
zoomOut: function() {
|
||||
// summary: Zoom out by one level (unless minimum reached).
|
||||
this.setZoom(this.zoom - 1);
|
||||
this.download();
|
||||
return this;
|
||||
},
|
||||
zoomOut: function() {
|
||||
// summary: Zoom out by one level (unless minimum reached).
|
||||
this.setZoom(this.zoom - 1);
|
||||
this.download();
|
||||
return this;
|
||||
},
|
||||
|
||||
setZoom: function(zoom) {
|
||||
if (zoom < this.MINSCALE || zoom > this.MAXSCALE) return this;
|
||||
// summary: Redraw the map at a new zoom level.
|
||||
this.zoom = zoom;
|
||||
this._setScaleFactor();
|
||||
this._blankTiles();
|
||||
this.setCentre({
|
||||
lat: this.centrelat,
|
||||
lon: this.centrelon
|
||||
});
|
||||
this.updateUIs(true, true);
|
||||
return this;
|
||||
},
|
||||
setZoom: function(zoom) {
|
||||
if (zoom < this.MINSCALE || zoom > this.MAXSCALE) return this;
|
||||
// summary: Redraw the map at a new zoom level.
|
||||
this.zoom = zoom;
|
||||
this._setScaleFactor();
|
||||
this._blankTiles();
|
||||
this.setCentre({
|
||||
lat: this.centrelat,
|
||||
lon: this.centrelon
|
||||
});
|
||||
this.updateUIs(true, true);
|
||||
return this;
|
||||
},
|
||||
|
||||
_setScaleFactor: function() {
|
||||
// summary: Calculate the scaling factor for this zoom level.
|
||||
this.zoomfactor = this.MASTERSCALE/Math.pow(2, 13 - this.zoom);
|
||||
},
|
||||
_setScaleFactor: function() {
|
||||
// summary: Calculate the scaling factor for this zoom level.
|
||||
this.zoomfactor = this.MASTERSCALE/Math.pow(2, 13 - this.zoom);
|
||||
},
|
||||
|
||||
// ----------------------
|
||||
// Elastic band redrawing
|
||||
// ----------------------
|
||||
// Elastic band redrawing
|
||||
|
||||
clearElastic: function() {
|
||||
// summary: Remove the elastic band used to draw new ways.
|
||||
this.elastic.clear();
|
||||
},
|
||||
clearElastic: function() {
|
||||
// summary: Remove the elastic band used to draw new ways.
|
||||
this.elastic.clear();
|
||||
},
|
||||
|
||||
drawElastic: function(x1,y1,x2,y2) {
|
||||
// summary: Draw the elastic band (for new ways) between two points.
|
||||
this.elastic.clear();
|
||||
// **** Next line is SVG-specific
|
||||
this.elastic.rawNode.setAttribute("pointer-events","none");
|
||||
this.elastic.createPolyline( [{ x:x1, y:y1 }, { x:x2, y:y2 }] ).setStroke( {
|
||||
color: [0, 0, 0, 1],
|
||||
style: 'Solid',
|
||||
width: 1
|
||||
});
|
||||
},
|
||||
drawElastic: function(x1,y1,x2,y2) {
|
||||
// summary: Draw the elastic band (for new ways) between two points.
|
||||
this.elastic.clear();
|
||||
// **** Next line is SVG-specific
|
||||
this.elastic.rawNode.setAttribute("pointer-events","none");
|
||||
this.elastic.createPolyline( [{ x:x1, y:y1 }, { x:x2, y:y2 }] ).setStroke( {
|
||||
color: [0, 0, 0, 1],
|
||||
style: 'Solid',
|
||||
width: 1
|
||||
});
|
||||
},
|
||||
|
||||
// -------------
|
||||
// Tile handling
|
||||
// ** FIXME: see docs
|
||||
loadTiles: function() {
|
||||
// summary: Load all tiles for the current viewport. This is a bare-bones function
|
||||
// at present: it needs configurable URLs (not just Bing), attribution/logo
|
||||
// support, and to be 'nudgable' (i.e. adjust the offset).
|
||||
var tl = this.locationCoord({
|
||||
// -------------
|
||||
// Tile handling
|
||||
// ** FIXME: see docs
|
||||
loadTiles: function() {
|
||||
// summary: Load all tiles for the current viewport. This is a bare-bones function
|
||||
// at present: it needs configurable URLs (not just Bing), attribution/logo
|
||||
// support, and to be 'nudgable' (i.e. adjust the offset).
|
||||
var tl = this.locationCoord({
|
||||
lat: this.extent.north,
|
||||
lon: this.extent.west
|
||||
}, this.zoom),
|
||||
@@ -302,208 +307,208 @@ declare("iD.renderer.Map", null, {
|
||||
seen = [],
|
||||
coord = { z: this.zoom };
|
||||
|
||||
for (coord.x = tl.x; coord.x <= br.x; coord.x++) {
|
||||
for (coord.y = tl.y; coord.y <= br.y; coord.y++) {
|
||||
if (!this._getTile(coord)) {
|
||||
this._fetchTile(coord);
|
||||
for (coord.x = tl.x; coord.x <= br.x; coord.x++) {
|
||||
for (coord.y = tl.y; coord.y <= br.y; coord.y++) {
|
||||
if (!this._getTile(coord)) {
|
||||
this._fetchTile(coord);
|
||||
}
|
||||
seen.push(iD.Util.tileKey(coord));
|
||||
}
|
||||
seen.push(iD.Util.tileKey(coord));
|
||||
}
|
||||
}
|
||||
|
||||
_.each(_.without(tileKeys, seen), _.bind(function(key) {
|
||||
delete this.tiles[key];
|
||||
}, this));
|
||||
},
|
||||
_.each(_.without(tileKeys, seen), _.bind(function(key) {
|
||||
delete this.tiles[key];
|
||||
}, this));
|
||||
},
|
||||
|
||||
_fetchTile: function(coord) {
|
||||
// summary: Load a tile image at the given tile co-ordinates.
|
||||
var t = this.tilegroup.createImage({
|
||||
x: Math.floor(this.lon2coord(this.tile2lon(coord.x))),
|
||||
y: Math.floor(this.lat2coord(this.tile2lat(coord.y))),
|
||||
width: 256,
|
||||
height: 256,
|
||||
src: this._tileURL(coord)
|
||||
});
|
||||
this._assignTile(coord, t);
|
||||
},
|
||||
_fetchTile: function(coord) {
|
||||
// summary: Load a tile image at the given tile co-ordinates.
|
||||
var t = this.tilegroup.createImage({
|
||||
x: Math.floor(this.lon2coord(this.tile2lon(coord.x))),
|
||||
y: Math.floor(this.lat2coord(this.tile2lat(coord.y))),
|
||||
width: 256,
|
||||
height: 256,
|
||||
src: this._tileURL(coord)
|
||||
});
|
||||
this._assignTile(coord, t);
|
||||
},
|
||||
|
||||
_getTile: function(coord) {
|
||||
// summary: See if this tile is already loaded.
|
||||
return this.tiles[iD.Util.tileKey(coord)];
|
||||
},
|
||||
_getTile: function(coord) {
|
||||
// summary: See if this tile is already loaded.
|
||||
return this.tiles[iD.Util.tileKey(coord)];
|
||||
},
|
||||
|
||||
_assignTile: function(coord, t) {
|
||||
// summary: Store a reference to the tile so we know it's loaded.
|
||||
this.tiles[iD.Util.tileKey(coord)] = t;
|
||||
},
|
||||
_assignTile: function(coord, t) {
|
||||
// summary: Store a reference to the tile so we know it's loaded.
|
||||
this.tiles[iD.Util.tileKey(coord)] = t;
|
||||
},
|
||||
|
||||
_tileURL: function(coord) {
|
||||
// summary: Calculate the URL for a tile at the given co-ordinates.
|
||||
var u = '';
|
||||
for (var zoom = coord.z; zoom > 0; zoom--) {
|
||||
var byte = 0;
|
||||
var mask = 1 << (zoom - 1);
|
||||
if ((coord.x & mask) !== 0) byte++;
|
||||
if ((coord.y & mask) !== 0) byte += 2;
|
||||
u += byte.toString();
|
||||
}
|
||||
return this.tilebaseURL
|
||||
.replace('$z', coord.z)
|
||||
.replace('$x', coord.x)
|
||||
.replace('$y', coord.y)
|
||||
.replace('$quadkey', u);
|
||||
},
|
||||
_tileURL: function(coord) {
|
||||
// summary: Calculate the URL for a tile at the given co-ordinates.
|
||||
var u = '';
|
||||
for (var zoom = coord.z; zoom > 0; zoom--) {
|
||||
var byte = 0;
|
||||
var mask = 1 << (zoom - 1);
|
||||
if ((coord.x & mask) !== 0) byte++;
|
||||
if ((coord.y & mask) !== 0) byte += 2;
|
||||
u += byte.toString();
|
||||
}
|
||||
return this.tilebaseURL
|
||||
.replace('$z', coord.z)
|
||||
.replace('$x', coord.x)
|
||||
.replace('$y', coord.y)
|
||||
.replace('$quadkey', u);
|
||||
},
|
||||
|
||||
_blankTiles: function() {
|
||||
// summary: Unload all tiles and remove from the display.
|
||||
this.tilegroup.clear();
|
||||
this.tiles = {};
|
||||
},
|
||||
_blankTiles: function() {
|
||||
// summary: Unload all tiles and remove from the display.
|
||||
this.tilegroup.clear();
|
||||
this.tiles = {};
|
||||
},
|
||||
|
||||
// -------------------------------------------
|
||||
// Co-ordinate management, dragging and redraw
|
||||
// -------------------------------------------
|
||||
// Co-ordinate management, dragging and redraw
|
||||
|
||||
startDrag: function(e) {
|
||||
// summary: Start dragging the map in response to a mouse-down.
|
||||
// e: MouseEvent The mouse-down event that triggered it.
|
||||
var srcElement = (e.gfxTarget === this.backdrop) ?
|
||||
e.gfxTarget : e.gfxTarget.parent;
|
||||
Event.stop(e);
|
||||
this.dragging = true;
|
||||
this.dragged = false;
|
||||
this.dragx = this.dragy=NaN;
|
||||
this.startdragx = e.clientX;
|
||||
this.startdragy = e.clientY;
|
||||
this.dragconnect = srcElement.connect("onmouseup", _.bind(this.endDrag, this));
|
||||
},
|
||||
startDrag: function(e) {
|
||||
// summary: Start dragging the map in response to a mouse-down.
|
||||
// e: MouseEvent The mouse-down event that triggered it.
|
||||
var srcElement = (e.gfxTarget === this.backdrop) ?
|
||||
e.gfxTarget : e.gfxTarget.parent;
|
||||
Event.stop(e);
|
||||
this.dragging = true;
|
||||
this.dragged = false;
|
||||
this.dragx = this.dragy=NaN;
|
||||
this.startdragx = e.clientX;
|
||||
this.startdragy = e.clientY;
|
||||
this.dragconnect = srcElement.connect("onmouseup", _.bind(this.endDrag, this));
|
||||
},
|
||||
|
||||
endDrag: function(e) {
|
||||
// summary: Stop dragging the map in response to a mouse-up.
|
||||
// e: MouseEvent The mouse-up event that triggered it.
|
||||
Event.stop(e);
|
||||
dojo.disconnect(this.dragconnect);
|
||||
this.dragging=false;
|
||||
this.dragtime=e.timeStamp;
|
||||
this.updateCoordsFromViewportPosition();
|
||||
if (Math.abs(e.clientX - this.startdragx) < 3 &&
|
||||
Math.abs(e.clientY - this.startdragy) < 3) {
|
||||
return;
|
||||
}
|
||||
this.download();
|
||||
},
|
||||
endDrag: function(e) {
|
||||
// summary: Stop dragging the map in response to a mouse-up.
|
||||
// e: MouseEvent The mouse-up event that triggered it.
|
||||
Event.stop(e);
|
||||
dojo.disconnect(this.dragconnect);
|
||||
this.dragging=false;
|
||||
this.dragtime=e.timeStamp;
|
||||
this.updateCoordsFromViewportPosition();
|
||||
if (Math.abs(e.clientX - this.startdragx) < 3 &&
|
||||
Math.abs(e.clientY - this.startdragy) < 3) {
|
||||
return;
|
||||
}
|
||||
this.download();
|
||||
},
|
||||
|
||||
processMove: function(e) {
|
||||
// summary: Drag the map to a new origin.
|
||||
// e: MouseEvent The mouse-move event that triggered it.
|
||||
var x = e.clientX;
|
||||
var y = e.clientY;
|
||||
if (this.dragging) {
|
||||
if (this.dragx) {
|
||||
this.containerx += (x - this.dragx);
|
||||
this.containery += (y - this.dragy);
|
||||
this.updateOrigin();
|
||||
this.dragged=true;
|
||||
}
|
||||
this.dragx = x;
|
||||
this.dragy = y;
|
||||
} else {
|
||||
this.controller.entityMouseEvent(e,null);
|
||||
}
|
||||
},
|
||||
processMove: function(e) {
|
||||
// summary: Drag the map to a new origin.
|
||||
// e: MouseEvent The mouse-move event that triggered it.
|
||||
var x = e.clientX;
|
||||
var y = e.clientY;
|
||||
if (this.dragging) {
|
||||
if (this.dragx) {
|
||||
this.containerx += (x - this.dragx);
|
||||
this.containery += (y - this.dragy);
|
||||
this.updateOrigin();
|
||||
this.dragged=true;
|
||||
}
|
||||
this.dragx = x;
|
||||
this.dragy = y;
|
||||
} else {
|
||||
this.controller.entityMouseEvent(e,null);
|
||||
}
|
||||
},
|
||||
|
||||
updateOrigin: function() {
|
||||
// summary: Tell Dojo to update the viewport origin.
|
||||
this.container.setTransform([Matrix.translate(this.containerx, this.containery)]);
|
||||
this.tilegroup.setTransform([Matrix.translate(this.containerx, this.containery)]);
|
||||
},
|
||||
updateOrigin: function() {
|
||||
// summary: Tell Dojo to update the viewport origin.
|
||||
this.container.setTransform([Matrix.translate(this.containerx, this.containery)]);
|
||||
this.tilegroup.setTransform([Matrix.translate(this.containerx, this.containery)]);
|
||||
},
|
||||
|
||||
_mouseEvent: function(e) {
|
||||
// summary: Catch mouse events on the surface but not the tiles - in other words,
|
||||
// on drawn items that don't have their own hitzones, like the fill of a shape.
|
||||
if (e.type=='mousedown') { this.startDrag(e); }
|
||||
// ** FIXME: we may want to reinstate this at some point...
|
||||
// this.controller.entityMouseEvent(e,null);
|
||||
},
|
||||
_mouseEvent: function(e) {
|
||||
// summary: Catch mouse events on the surface but not the tiles - in other words,
|
||||
// on drawn items that don't have their own hitzones, like the fill of a shape.
|
||||
if (e.type=='mousedown') { this.startDrag(e); }
|
||||
// ** FIXME: we may want to reinstate this at some point...
|
||||
// this.controller.entityMouseEvent(e,null);
|
||||
},
|
||||
|
||||
updateCoordsFromViewportPosition: function(e) {
|
||||
// summary: Update centre and bbox from the current viewport origin.
|
||||
this._updateCoords(this.containerx, this.containery);
|
||||
},
|
||||
updateCoordsFromViewportPosition: function(e) {
|
||||
// summary: Update centre and bbox from the current viewport origin.
|
||||
this._updateCoords(this.containerx, this.containery);
|
||||
},
|
||||
|
||||
setCentre: function(loc) {
|
||||
// summary: Update centre and bbox to a specified lat/lon.
|
||||
var coord = this.locationCoord(loc, this.zoom);
|
||||
this._updateCoords(
|
||||
-coord.x - this.mapwidth / 2,
|
||||
-coord.y - this.mapheight / 2);
|
||||
return this;
|
||||
},
|
||||
setCentre: function(loc) {
|
||||
// summary: Update centre and bbox to a specified lat/lon.
|
||||
var coord = this.locationCoord(loc, this.zoom);
|
||||
this._updateCoords(
|
||||
-coord.x - this.mapwidth / 2,
|
||||
-coord.y - this.mapheight / 2);
|
||||
return this;
|
||||
},
|
||||
|
||||
setCenter: function(loc) { this.setCentre(loc); },
|
||||
setCenter: function(loc) { this.setCentre(loc); },
|
||||
|
||||
_updateCoords:function(x, y) {
|
||||
// summary: Set centre and bbox.
|
||||
this.containerx = x;
|
||||
this.containery = y;
|
||||
this.updateOrigin();
|
||||
this.centrelon = this.coord2lon(-x + this.mapwidth/2);
|
||||
this.centrelat = this.coord2lat(-y + this.mapheight/2);
|
||||
_updateCoords:function(x, y) {
|
||||
// summary: Set centre and bbox.
|
||||
this.containerx = x;
|
||||
this.containery = y;
|
||||
this.updateOrigin();
|
||||
this.centrelon = this.coord2lon(-x + this.mapwidth/2);
|
||||
this.centrelat = this.coord2lat(-y + this.mapheight/2);
|
||||
|
||||
this.extent = {
|
||||
north: this.coord2lat(-y),
|
||||
south: this.coord2lat(-y + this.mapheight),
|
||||
west: this.coord2lon(-x),
|
||||
east: this.coord2lon(-x + this.mapwidth)
|
||||
};
|
||||
this.extent = {
|
||||
north: this.coord2lat(-y),
|
||||
south: this.coord2lat(-y + this.mapheight),
|
||||
west: this.coord2lon(-x),
|
||||
east: this.coord2lon(-x + this.mapwidth)
|
||||
};
|
||||
|
||||
this.loadTiles();
|
||||
},
|
||||
this.loadTiles();
|
||||
},
|
||||
|
||||
clickSurface:function(e) {
|
||||
// summary: Handle a click on an empty area of the map.
|
||||
if (this.dragged && e.timeStamp==this.dragtime) { return; }
|
||||
this.controller.entityMouseEvent(e,null);
|
||||
},
|
||||
clickSurface:function(e) {
|
||||
// summary: Handle a click on an empty area of the map.
|
||||
if (this.dragged && e.timeStamp==this.dragtime) { return; }
|
||||
this.controller.entityMouseEvent(e,null);
|
||||
},
|
||||
|
||||
// -----------------------
|
||||
// Co-ordinate conversions
|
||||
// -----------------------
|
||||
// Co-ordinate conversions
|
||||
|
||||
latp2coord:function(a) { return -(a-this.baselatp)*this.zoomfactor; },
|
||||
coord2latp:function(a) { return a/-this.zoomfactor+this.baselatp; },
|
||||
lon2coord:function(a) { return (a-this.baselon)*this.zoomfactor; },
|
||||
coord2lon:function(a) { return a/this.zoomfactor+this.baselon; },
|
||||
lon2screen:function(a) { return this.lon2coord(a) + this.marginBox.l + this.containerx; },
|
||||
latp2coord:function(a) { return -(a-this.baselatp)*this.zoomfactor; },
|
||||
coord2latp:function(a) { return a/-this.zoomfactor+this.baselatp; },
|
||||
lon2coord:function(a) { return (a-this.baselon)*this.zoomfactor; },
|
||||
coord2lon:function(a) { return a/this.zoomfactor+this.baselon; },
|
||||
lon2screen:function(a) { return this.lon2coord(a) + this.marginBox.l + this.containerx; },
|
||||
|
||||
lat2latp:function(a) { return 180/Math.PI * Math.log(Math.tan(Math.PI/4+a*(Math.PI/180)/2)); },
|
||||
latp2lat:function(a) { return 180/Math.PI * (2 * Math.atan(Math.exp(a*Math.PI/180)) - Math.PI/2); },
|
||||
lat2coord:function(a) { return -(this.lat2latp(a)-this.baselatp)*this.zoomfactor; },
|
||||
coord2lat:function(a) { return this.latp2lat(a/-this.zoomfactor+this.baselatp); },
|
||||
lat2screen:function(a) { return this.lat2coord(a) + this.marginBox.t + this.containery; },
|
||||
lat2latp:function(a) { return 180/Math.PI * Math.log(Math.tan(Math.PI/4+a*(Math.PI/180)/2)); },
|
||||
latp2lat:function(a) { return 180/Math.PI * (2 * Math.atan(Math.exp(a*Math.PI/180)) - Math.PI/2); },
|
||||
lat2coord:function(a) { return -(this.lat2latp(a)-this.baselatp)*this.zoomfactor; },
|
||||
coord2lat:function(a) { return this.latp2lat(a/-this.zoomfactor+this.baselatp); },
|
||||
lat2screen:function(a) { return this.lat2coord(a) + this.marginBox.t + this.containery; },
|
||||
|
||||
locationCoord: function(ll, z) {
|
||||
var z2 = Math.pow(2, z), d2r = Math.PI / 180;
|
||||
return {
|
||||
z: z,
|
||||
x: Math.floor((ll.lon + 180) / 360 * z2),
|
||||
y: Math.floor((1 - Math.log(Math.tan(ll.lat * d2r) +
|
||||
1 / Math.cos(ll.lat * d2r)) / Math.PI) / 2 * z2)
|
||||
};
|
||||
},
|
||||
lon2tile:function(a) { return (Math.floor((a+180)/360*Math.pow(2,this.zoom))); },
|
||||
lat2tile:function(a) { return (Math.floor((1-Math.log(Math.tan(a*Math.PI/180) + 1/Math.cos(a*Math.PI/180))/Math.PI)/2 *Math.pow(2,this.zoom))); },
|
||||
tile2lon:function(a) { return (a/Math.pow(2,this.zoom)*360-180); },
|
||||
tile2lat:function(a) {
|
||||
var n=Math.PI-2*Math.PI*a/Math.pow(2,this.zoom);
|
||||
return (180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
|
||||
},
|
||||
locationCoord: function(ll, z) {
|
||||
var z2 = Math.pow(2, z), d2r = Math.PI / 180;
|
||||
return {
|
||||
z: z,
|
||||
x: Math.floor((ll.lon + 180) / 360 * z2),
|
||||
y: Math.floor((1 - Math.log(Math.tan(ll.lat * d2r) +
|
||||
1 / Math.cos(ll.lat * d2r)) / Math.PI) / 2 * z2)
|
||||
};
|
||||
},
|
||||
lon2tile:function(a) { return (Math.floor((a+180)/360*Math.pow(2,this.zoom))); },
|
||||
lat2tile:function(a) { return (Math.floor((1-Math.log(Math.tan(a*Math.PI/180) + 1/Math.cos(a*Math.PI/180))/Math.PI)/2 *Math.pow(2,this.zoom))); },
|
||||
tile2lon:function(a) { return (a/Math.pow(2,this.zoom)*360-180); },
|
||||
tile2lat:function(a) {
|
||||
var n=Math.PI-2*Math.PI*a/Math.pow(2,this.zoom);
|
||||
return (180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
|
||||
},
|
||||
|
||||
// Turn event co-ordinates into map co-ordinates
|
||||
// Turn event co-ordinates into map co-ordinates
|
||||
|
||||
mouseX: function(e) { return e.clientX - this.marginBox.l - this.containerx; },
|
||||
mouseY: function(e) { return e.clientY - this.marginBox.t - this.containery; }
|
||||
});
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// End of module
|
||||
mouseX: function(e) { return e.clientX - this.marginBox.l - this.containerx; },
|
||||
mouseY: function(e) { return e.clientY - this.marginBox.t - this.containery; }
|
||||
});
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// End of module
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user