Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

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;
}



Thank you in advance and I make my apologies for my english I'll hope is everything clear ;)

Bye R


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?

Bye

R


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

Bye R

share|improve this question

1 Answer 1

you can catch your opened(active) popup with this way:

map.popups[a]

you can change so update its content:

map.popups[a].contentHTML = 'Test Content';
map.popups[a].redraw();

or

map.popups[a].setContentHTML = 'Test Content'

you can show or hide your popup:

map.popups[a].show();
map.popups[a].hide();

you can update position of your popup:

map.popups[a].lonlat.lon = 10;
map.popups[a].lonlat.lat = 10;
map.popups[a].updatePosition();

for openlayers cluster you should check out Cluster Strategy Example here. Only one thing you should do is that define fillColor or externalGraphic for your cluster.

          var style = new OpenLayers.Style({
                pointRadius: "${radius}",
                fillColor: "${getColor}",
                fillOpacity: 0.8,
                strokeColor: "#cc6633",
                strokeWidth: 2,
                strokeOpacity: 0.8
            }, {
                context: {
                    radius: function(feature) {
                        return Math.min(feature.attributes.count, 7) + 3;
                    },
                    getColor: function(feature) {
                        return // Your color selection logic;
                    }
                }
            });

As the last question, i dont understand very well what you want? but try to use removeFeatures instead of destroyFeatures....

i hope it helps you...

share|improve this answer
    
Thank you for the answer, tomorrow I try to add your code (now I don't have my notebook). For the last question I have try both destroy, remove and removeAll but I have the same feedback from OL. When I add a new features on vector layer after function: "destroy" or "remove" - I don't know what exactly happens - but if I click on new icon added nothing happens. In other words: removeFeatures or destroyFeatures -> layer clean without features -> addFeatures -> no popup shown.. Thank you again R –  crc_error Jun 4 '12 at 17:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.