Saturday 17 October 2015

openlayers 2 - Screen coordinates generated locate popup incorrectly


I'm using OpenLayers 2.13 for an application that create several maps. When the user click on a map a popup appears where the user clicked on the map. Sometime the popup is offset either east or west of where it should be. I used console.log to get the values from map.getLongLatFromViewPort(event.xy) and the event.xy that place the popup. The event.xy, when popup appears in the wrong location, has a value for event.xy.x that is not correct. Below is the code for the popup:


innovate.popupbox[mapID] = new OpenLayers.Popup.FramedCloud(
"innovate_info_popup_" + mapID,
map.getLonLatFromViewPortPx(event.xy),
boxSize,
content,
null,

true,
function() {
this.div.style.display = 'none';
map.panTo(innovate.lastPopupCenter[mapID]);
map.removePopup(innovate.popupbox[mapID]);
}
);

The following is how the map is built:


innovate.Map = function(mapID){

var currentObject = this;

this.map = null;
this.config = innovate.getUserConfigForMap(mapID);
this.innovateLayerObj = new innovate.Layers(this);
this.innovateControlsObj = new innovate.Controls(this);
this.clickControls = {};
this.mapClickControlIds = {};

//build map object

this.setMap = function(){
var baseLayerType = this.innovateLayerObj.getBaseLayerType();
this.map = new OpenLayers.Map('container-map'+mapID, {
allOverlays: false,
fallThrough : true,
projection: currentObject.config.projection,
controls: [
new OpenLayers.Control.PanZoomBar()
]
//,eventListeners: {"mouseout": innovate.handleOnMouseOutOnMap,"mouseover":innovate.handleOnMouseOverOnMap}

});

if(baseLayerType==="arcgiscache"){
this.map.setOptions({
maxExtent: new OpenLayers.Bounds(currentObject.config.maxExtent[0],currentObject.config.maxExtent[1],currentObject.config.maxExtent[2],currentObject.config.maxExtent[3])
});
}else if (baseLayerType==="bing"){
this.map.setOptions({
maxExtent: new OpenLayers.Bounds(currentObject.config.maxExtent[0],currentObject.config.maxExtent[1],currentObject.config.maxExtent[2],currentObject.config.maxExtent[3])
});

}
}

//set all the base layer as well as overlays
this.setLayers = function(){
var layer = null;
for (key in this.config['baseMap']) {
layer = this.innovateLayerObj.getLayer(this.config['baseMap'][key]);
this.map.addLayer(layer);
}


for (key in this.config['layers']) {
layer = this.innovateLayerObj.getLayer(this.config['layers'][key]);

if(this.config['initialDisplayLayer']){
if(key!=parseInt(this.config['initialDisplayLayer'])){
layer.setVisibility(false);
}
}
this.map.addLayer(layer);

}

if(this.config['layers'].length>1 && this.config['initialDisplayLayer']){
var layers = this.map.layers.slice(),count=0;
for(var i=0;i if(!(layers[i].isBaseLayer)){
if(count!=this.config['initialDisplayLayer']){
layers[i].setVisibility(false);
}
count++;

}
}

}
}

this.reactivateClickEvents = function(){
//first remove the click control from the map
//for some reason in dev, the click control was added twice!
//same issue did not arrise in local

//but adding code to delete the control and then add it back did the trick
for(var keys in this.map.controls){
if(this.mapClickControlIds[this.map.controls[keys].id]){
//alert("removed"+this.map.controls[keys].id);
this.map.controls[keys].deactivate();
this.map.removeControl(this.map.controls[keys]);
}
}
this.mapClickControlIds=[];


var control = null,layerName;
for (key in this.config['controls']) {

var controlName = this.config['controls'][key];
if(controlName.substr(0,6)=='click_'){
for(var layerIndx in this.config["layers"]){

layerName = this.innovateLayerObj.layerDefinitions[this.config["layers"][layerIndx]]["name"];
control = (this.innovateControlsObj[controlName]).call(this.innovateControlsObj,layerName);
if(control!=null){

this.clickControls[layerName] = control;
this.map.addControl(control);
control.activate();
this.mapClickControlIds[control.id]=1;
}

}
}
}


}

//set all the controls
this.setControls = function(){
var control = null,layerName;
for (key in this.config['controls']) {
var controlName = this.config['controls'][key];
if(controlName.substr(0,6)==='click_'){
for(var layerIndx in this.config["layers"]){


layerName = this.innovateLayerObj.layerDefinitions[this.config["layers"][layerIndx]]["name"];
control = (this.innovateControlsObj[controlName]).call(this.innovateControlsObj,layerName);
if(control!=null){
this.clickControls[layerName] = control;
this.map.addControl(control);
control.activate();
this.mapClickControlIds[control.id]=1;
}

}

}
else{
control = this.innovateControlsObj.getControl(controlName);
if(control!=null){
this.map.addControl(control);
}
}
}
}


/*
* Thus function builds map based on map id set to the current innovate.Map function
*/
this.buildMap=function(){
this.setMap();
this.setLayers();
this.setControls();

var baseLayerType = this.innovateLayerObj.getBaseLayerType();


if(currentObject.config.zoomToExtent){
this.map.zoomToExtent(new OpenLayers.Bounds(currentObject.config.zoomToExtent[0],currentObject.config.zoomToExtent[1],currentObject.config.zoomToExtent[2],currentObject.config.zoomToExtent[3]));
}else if(this.config.center){
var zoomLevel = this.config.defaultZoomLevel?this.config.defaultZoomLevel-this.config.startResolution:0;
var geographic = new OpenLayers.Projection("EPSG:4326");
var mercator = new OpenLayers.Projection(this.config["projection"]);
this.map.setCenter(new OpenLayers.LonLat(this.config.center[0], this.config.center[1]).transform(geographic,mercator),zoomLevel);

}else if(baseLayerType==="arcgiscache"){
this.map.zoomTo(this.config.startResolution);

}
}

}


Below is the event handler for the map:


this.click_radons = function(layerName) {
if (layerName == "State Boundaries") {
return null;
}
var map = innovateMapObj.map,

layer = null,
serviceURL = null,
layers = map.layers.slice(),
content = "",
desc = null,
img = null,
priority = null;

//because we don't want to query base layer
for (var i = 0; i < layers.length; i++) {

if (!(layers[i].isBaseLayer)) {
layer = layers[i];
serviceURL = layers[i].url;
break;
}
}


OpenLayers.ProxyHost = innovate.proxyURL;
return new OpenLayers.Control.WMSGetFeatureInfo({

layers: [layer],
url: serviceURL,
title: 'Identify features by clicking',
queryVisible: true,
eventListeners: {
getfeatureinfo: function(event) {
var thisObject = new innovate.Controls(innovateMapObj)
obj = thisObject.makeObjectOutOfResponse(event.text);

var boxSize = null;

var mapID = innovateMapObj.config.id;
//hide any open popup on click
if (innovate.popupbox[mapID]) {
map.removePopup(innovate.popupbox[mapID]);
innovate.popupbox[mapID].destroy();
//$("#innovate_info_popup_" + mapID).hide();
}
if ($.isEmptyObject(obj) || obj === false) {
return;
}

innovate.lastPopupCenter[mapID] = map.getCenter();

if (obj['radonzone'] == 1) {
desc = "Zone 1 counties have a predicted average indoor radon screening level greater than 4 pCi/L (picocuries per liter) (red zones)";
priority = "Highest Potential";
img = "3b6a386668a6d07b8d8e029744820282";
} else if (obj['radonzone'] == 2) {
desc = "Zone 2 counties have a predicted average indoor radon screening level between 2 and 4 pCi/L (orange zones)";
priority = "Moderate Potential";
img = "52edb92fef3b3447d910ea3f4e3bad06";

} else if (obj['radonzone'] == 3) {
desc = "Zone 3 counties have a predicted average indoor radon screening level less than 2 pCi/L (yellow zones)";
priority = "Low Potential";
img = "d1573b09a0505bef245b2a380a18e380";
}
var stateName = obj['statename'], initCapedStateName = "";
stateName = stateName.split(" ");
for (var keys in stateName) {
initCapedStateName += stateName[keys].substr(0, 1) + stateName[keys].substr(1).toLowerCase() + " ";
}


var imgURL = innovate.mapServiceBaseURL["legend"] + innovateMapObj.config.legend["url"] + "/../0/images/" + img;
content = "
" + obj['namelsad'] + ", " + initCapedStateName + "
" +
"
Radon risk zone: " + obj['radonzone'] + "
" +
"" +
"" +
"
\"\"
" + desc + "" + priority + "
";


innovate.popupbox[mapID] = new OpenLayers.Popup.FramedCloud(

"innovate_info_popup_" + mapID,
map.getLonLatFromViewPortPx(event.xy),
boxSize,
content,
null,
true,
function() {
this.div.style.display = 'none';
map.panTo(innovate.lastPopupCenter[mapID]);
map.removePopup(innovate.popupbox[mapID]);

}
);

map.addPopup(innovate.popupbox[mapID]);

}
}
});

}



It seem as though something is causing the screen coordinates to sometime be shifted to the left or right of where the user click. Any advice would helpful.




No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...