I'm trying to create a website for vehicles localization on map, but i have some problem with openlayers. This is my first time with OL...
What I would do is: - add and update features (my vehicles) on map. DONE - follow only vehicles visible on screen. DONE - add and update popup on map. PARTIAL 1 - add clustering options. NO - remove and add features in run time. PARTIAL 2
I have a series of functions called by runtime engine for updating values.
PARTIAL 1 Popup is shown correclt popup is shown correctly but what I want to do is update it values and position when vehicle is updated (function drawPosition) - only if popup is active -
STRATEGY I am a little bit confused about clustering mode. Now I have a series of png with different color (which represent the status of vehicles). I would create groups of icons with same color, visibles only by at some zoom level. Is it possible to create a vector (circles with different color) to represent clusters if I used PNG icons as markers? Or i must create a big PNG that represent the cluster?
PARTIAL 2 A user can change vehicles shown on map with a jquery dialog. JS call: pulisiMappa() to clean map from all features and call again drawPosition() to add vehicles choosed by user.
It works great but with my code i lose something. I don't know if with destroyFeatures() I lose the event.register on l_elements (my vector layer) or I lose something about SelectFeature
Where's the problem?
this is my code:
var map;
var justLoaded = 0
var points = [];
var storico = { path: null, pos: null, pts: [], viaggio: { viaggio: null, start: null, stop: null} };
var eventPoints = [];
var select_feature_control;
var l_elements, m_osm, m_google_str, m_google_sat, m_google_ril, m_google_satH, m_ovi, m_base, m_base_et;
// WGS84 -> PTV_MERCATOR
OpenLayers.Projection.addTransform("EPSG:4326", "PTV_MERCATOR", function (point) { var RPI = Math.PI * 6371000.0; var x = point.x * RPI / 180; var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180); y = y * RPI / 180; point.x = x; point.y = y; });
// PTV_MERCATOR -> WGS84
OpenLayers.Projection.addTransform("PTV_MERCATOR", "EPSG:4326", function (point) { var RPI = Math.PI * 6371000.0; var lon = (point.x / RPI) * 180; var lat = (point.y / RPI) * 180; lat = 180 / Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2); point.x = lon; point.y = lat; });
function initMap() {
map = new OpenLayers.Map({
div: "mapContainer",
projection: new OpenLayers.Projection("EPSG:4326"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
controls: [
new OpenLayers.Control.Attribution(),
new OpenLayers.Control.TouchNavigation({
dragPanOptions: {
interval: 100,
enableKinetic: true
}
}),
new OpenLayers.Control.ScaleLine({}),
new OpenLayers.Control.LayerSwitcher(),
new OpenLayers.Control.NavToolbar(),
new OpenLayers.Control.KeyboardDefaults({ autoActivate: true })
],
units: "m",
numZoomLevels: 20,
maxResolution: 9783.939619140625, /*156543.0399,*/
minResolution: 0.5971642833948135,
maxExtent: new OpenLayers.Bounds(-19900000.0, -7300000.0, 19900000.0, 18600000.0),
restrictExtent: new OpenLayers.Bounds(-19900000.0, -7300000.0, 19900000.0, 18600000.0)
});
var style = new OpenLayers.Style({
pointRadius: "${radius}",
fillColor: "#ffcc66",
fillOpacity: 0.8,
strokeColor: "#cc6633",
strokeWidth: 2,
strokeOpacity: 0.8,
externalGraphic: "${icona_elemento}",
graphicWidth: 38,
graphicHeight: 38,
rotation: "${angle}",
fillOpacity: 1,
graphicZIndex: 10,
label: "${nome_elemento}",
labelAlign: "cb",
labelYOffset: -24,
fontOpacity: 1,
fontWeight: 600,
fontColor: "#000",
fontSize: "10px",
fontFamily: "\"Lucida Grande\", \"Lucida Sans Unicode\", Helvetica, Arial, Verdana, sans-serif"
}, {
context: {
externalGraphic: null,
radius: function (feature) {
return Math.min(feature.attributes.count, 7) + 3;
}
}
});
m_osm = new OpenLayers.Layer.OSM();
m_google_ril = new OpenLayers.Layer.Google("Google Rillievo",{ type: google.maps.MapTypeId.TERRAIN });
m_google_str = new OpenLayers.Layer.Google("Google Stradale", { numZoomLevels: 20, isBaseLayer: true, sphericalMercator: true });
m_google_satH = new OpenLayers.Layer.Google("Google Satellite Ibrida",{ type: google.maps.MapTypeId.HYBRID, numZoomLevels: 20 });
m_google_sat = new OpenLayers.Layer.Google("Google Satellite", { type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 20, sphericalMercator:true });
m_ovi = new OpenLayers.Layer.XYZ("Nokia Ovi Maps",
["http://a.maptile.maps.svc.ovi.com/maptiler/maptile/newest/normal.day/${z}/${x}/${y}/256/png8",
"http://b.maptile.maps.svc.ovi.com/maptiler/maptile/newest/normal.day/${z}/${x}/${y}/256/png8"],
{ transitionEffect: 'resize', sphericalMercator: true, numZoomLevels: 18 });
l_elements = new OpenLayers.Layer.Vector("Veicoli", {
styleMap: new OpenLayers.StyleMap({
"default": style,
"select": {
cursor: "hand",
graphicWidth: 40,
graphicHeight: 40,
graphicZIndex: 11,
fillColor: "#8aeeef",
strokeColor: "#32a8a9"
}
}), /*
strategies: [
new OpenLayers.Strategy.Refresh(),
new OpenLayers.Strategy.Cluster()
],*/
renders: ['canvas', 'SVG', 'VML'],
rendererOptions: { zIndexing: true }
}
);
map.addLayers([m_osm, m_google_str, m_google_sat, m_ovi, m_google_ril, m_google_satH, l_elements]);
//setto il clip rect e lo zoom
var curClipRect = parent.getCartografiaClipRect();
var myClipRect = { left: curClipRect.left / 100000, top: curClipRect.top / 100000, right: curClipRect.right / 100000, bottom: curClipRect.bottom / 100000 }
var theRect = new OpenLayers.Bounds();
theRect.extend(new OpenLayers.LonLat(myClipRect.left, myClipRect.top).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
theRect.extend(new OpenLayers.LonLat(myClipRect.right, myClipRect.bottom).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
theRect.toBBOX();
map.zoomToExtent(theRect, true);
select_feature_control = new OpenLayers.Control.SelectFeature(l_elements, { multiple: false, toggle: true, hover: false });
map.addControl(select_feature_control);
select_feature_control.activate();
l_elements.events.on({
'featureselected': function (evt) {
var feature = evt.feature;
popup = new OpenLayers.Popup.FramedCloud("featurePopup",
feature.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(280, 63), feature.attributes.description, null, true, select_feature_control.unselect(feature));
feature.popup = popup;
popup.feature = feature;
map.addPopup(popup, true);
$('a[id$="_bubbleDetail"]').click(function () {
var myid = this.id.replace("_bubbleDetail", "");
if (parent.$("#cruscotto").dialog("isOpen") == false) { parent.$("#cruscotto").dialog("open"); }
parent.$(".box_container").not("#" + myid + "_boxContainer").removeClass("active");
parent.$("#" + myid + "_boxContainer").addClass("active");
parent.handleBubbleDetail(myid);
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
});
},
'featureunselected': function (evt) {
var feature = evt.feature;
if (feature.popup) {
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
}
});
justLoaded = 1;
parent.rebuildScene();
parent.setMapLoaded();
if (parent.document.location.href.indexOf("listaveicoli") >= 0) {
map.events.register('zoomend', this, changeZoomHandler);
map.events.register('moveend', this, changeZoomHandler);
}
}
function drawPosition(posInfo) {
// new feature
if (points["_" + posInfo.id] == undefined) {
var newPos = new OpenLayers.Feature.Vector();
var obj = { id: posInfo.id, follow: posInfo.follow, newpos: 1, _pt: newPos, _lb: null, loaded: 0 };
points["_" + posInfo.id] = obj;
}
if (posInfo.ico.indexOf("old_style")) {
var colore = posInfo.ico.split("_");
if (parseInt(posInfo.dir) 0)
pts = pts + ",";
pts = pts + myId;
}
else
points[pos].follow = 0;
}
}
var todo = 1;
parent.setMezziToFollow(pts);
};
/* ----------------------------------------------------------------------------------------------------------------------------- */
//map clean
function pulisciMappa() {
for (var myId in points) {
var tmpInfo = { id: myId.replace("_", "") }
removePosition(tmpInfo);
}
points = [];
// deleteViaggio();
// deletePosizioneStorico();
// deleteStorico();
// deleteEventi();
}
//remove features
function removePosition(posInfo) {
//id veicolo
var myId = posInfo.id;
var _punto = points["_" + posInfo.id]._pt;
if (points["_" + posInfo.id].loaded == 1) {
l_elements.destroyFeatures(_punto);
}
points["_" + posInfo.id]._pt = null;
points["_" + posInfo.id]._lb = null;
points["_" + posInfo.id].loaded = 0;
}
I'll hope everything is clear ;)
EDIT 1: about partial 1 and 2...
it's me again..
Thanks Aragon, with your code now I can update popup content and its position.
I added this code to drawPosition() function:
if(map.popups.length > 0) {
if(_punto.id == map.popups[0].id) {
map.popups[0].setContentHTML(posInfo.bubble);
map.popups[0].lonlat.lon = pointCoord.x;
map.popups[0].lonlat.lat = pointCoord.y;
map.popups[0].updatePosition();
}
}
and everything works fine.
Now I m trying to fix the "event listner" on features when I update vehicles to show.
When I select some vehicles from a jquery dialog, a backend function cleans the vector layer (l_elements) and when layer is clean, there is a "for" cycle that make a call of drawPosition() to add a new feature for every vehicle selected.
Everything works good except the "event listener" over this features.
If I click on every features nothing happens.. :(
I have this code in init() function:
select_feature_control = new OpenLayers.Control.SelectFeature(l_elements, { multiple: false, toggle: true, hover: false });
map.addControl(select_feature_control);
select_feature_control.activate();
l_elements.events.on(
{
'featureselected': function (evt) {
alert("ciao");
var feature = evt.feature;
popup = new OpenLayers.Popup.FramedCloud("featurePopup",
feature.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(280, 63), feature.attributes.description, null, true, select_feature_control.unselect(feature));
feature.popup = popup;
popup.feature = feature;
popup.id = feature.id;
map.addPopup(popup, true);
$('a[id$="_bubbleDetail"]').click(function () {
var myid = this.id.replace("_bubbleDetail", "");
if (parent.$("#cruscotto").dialog("isOpen") == false) { parent.$("#cruscotto").dialog("open"); }
parent.$(".box_container").not("#" + myid + "_boxContainer").removeClass("active");
parent.$("#" + myid + "_boxContainer").addClass("active");
parent.handleBubbleDetail(myid);
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
});
},
'featureunselected': function (evt) {
var feature = evt.feature;
if (feature.popup) {
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
}
});
Should I move it in drawPosition function?
EDIT 2:
PARTIAL 2 is solved: I made this changes to my code:
drawPosition()
//_punto.id = posInfo.id;
_punto.attributes = {
angle: posInfo.dir,
title: posInfo.label,
id: posInfo.id,
description: posInfo.bubble,
icona_elemento: icona_elemento,
nome_elemento: posInfo.label
};
init()
'featureselected': function (evt) {
var feature = evt.feature;
popup = new OpenLayers.Popup.FramedCloud("featurePopup",
feature.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(280, 63), feature.attributes.description, null, true, select_feature_control.unselect(feature));
feature.popup = popup;
popup.feature = feature;
popup.id = feature.attributes.id;
map.addPopup(popup, true);
},
And everything works good ;)
So.. - partial 1 is ok - partial 2 is now ok