Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenLayers latitude inaccurately captured in Webkit Mobile browsers

I am programming a page with a Map where I need to capture the location of the Tap/Click on a map and store the coordinates. I am using OpenLayers js. On desktop browsers (IE/FF/Chrome), this is working fine. On mobile devices, the tap is getting captured correctly on the default Android browser (both in real devices and emulators).

However on mobile webkit browsers (iPhone Safari & Android Chrome Beta), we are having a problem where the tap is getting captured for a few pixels higher (towards the north) of the actual tap. The error is not fixed (so, I can't just add 100 to the event's xy to recalibrate the top.)

Here is the code I am using as the clickhandler:

OpenLayers.Control.ClickHandler = OpenLayers.Class(OpenLayers.Control, {                
    defaultHandlerOptions: {
        'single': true,
        'double': false,
        'pixelTolerance': 0,
        'stopSingle': false,
        'stopDouble': false
    },

    initialize: function(options) {
        this.handlerOptions = OpenLayers.Util.extend(
            {}, this.defaultHandlerOptions
        );
        OpenLayers.Control.prototype.initialize.apply(
            this, arguments
        ); 
        this.handler = new OpenLayers.Handler.Click(
            this, {
                'click': this.trigger
            }, this.handlerOptions
        );
    }, 

    trigger: function(e) {
        that.inputLonLat_EPSG4326 = null;

        var lonlat = that.inputMap.getLonLatFromViewPortPx(e.xy);

        that.logMessage("XY " + e.xy);
        that.logMessage("LonLoat " + lonlat);

        that.inputMarkers.clearMarkers();


    that.inputMarkers.addMarker(new OpenLayers.Marker(lonlat,that.icons["green"].clone()));

    lonlat.transform(that.inputMap.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));

    that.inputLonLat_EPSG4326 = lonlat;
    // For the moderation sections
    $('#alertLatitude').val(that.inputLonLat_EPSG4326.lat);
    $('#alertLongitude').val(that.inputLonLat_EPSG4326.lon);

    //lonLat2.transform(that.inputMap.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));
    that.logMessage("Stored lat " + that.inputLonLat_EPSG4326.lat);
    that.logMessage("Stored lon " + that.inputLonLat_EPSG4326.lon);     

    that.callFunction(that.inputMapListener, e);
    }   
});

Should I be doing anything differently? Has anybody else seen the inaccuracy problem on mobile webkit browsers while using OpenLayers?

like image 240
Shreeni Avatar asked Nov 14 '22 05:11

Shreeni


1 Answers

I finally found the reason this is happening. It seems that on webkit mobile browsers, the x,y that the library seems to be getting (or deriving) is based on the page and not on the element in which the map is housed. Hence the calculations are off. It seems that the inaccuracy can't be solved by adding the xy of the map element or some such DOM-based figure too (I tried it.)

I solved it by housing the Map in an IFrame and then have the iFrame housed within the map element. This way the x,y as received by the map click handler is accurate within the iFrame and hence the lat, long is also accurate. Since both the parent and iFrame are from the same domain, there are no issues communicating back and forth.

To complete the context, the iFrame based solution is definitely compatible with BB 9 & above, Android Chrome, Android Default and iPhone Safari, as tested by me.

Check out the solution at - http://suat1.vocanic.net//saralee/apps/dengue_alert/ and the iFrame at http://suat1.vocanic.net//saralee/apps/dengue_alert/mobileMap.php (WIP versions liable to change or break with time)

like image 194
Shreeni Avatar answered Nov 16 '22 03:11

Shreeni