I have been trying to use both google maps and WMS layers as an option in the layerswitching panel. But when I switch the base layer from WMS to Google Maps layer and then back to WMS,

the bounds of the map do not come right and the map is not displayed properly. Even the vector overlay features which display correctly at 1st in the WMS, get crowded into small area on the google maps. I think there is some problem with the re-instantiation of the maps variable during layer switch, due to which the map bounds are not correct.

But still on the whole, please tell me how to solve this problem as it would be great to be able to use any map service in a single HTML page.

3 Answers 3


Is the WMS layer in the same projection as the Google layer? If not, you will have to handle the LayerSwitch event and reproject the overlay to make it align with the different projection. Note that the OpenLayers devs don't recommend mixing base layer projections, but in practice it can be made to work.

  • my WMS layer is not in the same projection. Your idea is good to handle the LayerSwitch event. Can you elaborate a bit and tell me how to do it? Apr 8, 2014 at 7:01

Try this code:

mapPanel = Ext.create('GeoExt.panel.Map', { border: false, region: "center", map: { projection: new OpenLayers.Projection("EPSG:900913"), displayProjection: new OpenLayers.Projection("EPSG:4326"), allOverlays: false, controls: [new OpenLayers.Control.Navigation() ] }, center: posicaoInicial, zoom: zoomInicial, layers: [ //Base Maps e Layers (../Scripts/global.js) satellite, hybrid, physical, streets, propriedadesGroup, patrimonioLayer, incraLayer ] });

See in the map options that i got the google projections 900913 and convert to the default projection 4326.

When instanciate the layers from google maps, use this params:

var physical = new OpenLayers.Layer.Google("Google Physical", { type: google.maps.MapTypeId.TERRAIN, "sphericalMercator": true }); physical.projection = new OpenLayers.Projection("EPSG:4326");


Actually, the trick is to patch the map's setBaseLayer() function.

I have some code here, but it's rather old and I haven't had time to look at it properly.

OpenLayers.Map.prototype.setBaseLayer = function(newBaseLayer) {

    var oldExtent = null;

    if (this.baseLayer)
        oldExtent = this.baseLayer.getExtent();       

        if (this.baseLayer.projection.projCode != newBaseLayer.projection.projCode) 
            var lb = new OpenLayers.Geometry.Point(oldExtent.left, oldExtent.bottom);
            var rt = new OpenLayers.Geometry.Point(oldExtent.right, oldExtent.top);

            OpenLayers.Projection.transform(lb, this.baseLayer.projection, newBaseLayer.projection);
            OpenLayers.Projection.transform(rt, this.baseLayer.projection, newBaseLayer.projection);

            oldExtent.left = lb.x;
            oldExtent.bottom = lb.y;
            oldExtent.right = rt.x;
            oldExtent.top = rt.y;                                   

    if (newBaseLayer != this.baseLayer)
        // ensure newBaseLayer is already loaded
        if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {

            // preserve center and scale when changing base layers
            var center = this.getCenter();

            var newResolution = OpenLayers.Util.getResolutionFromScale(this.getScale(), newBaseLayer.units);

            // make the old base layer invisible 
            if (this.baseLayer != null && !this.allOverlays)

            var oldBaseLayer = this.baseLayer;

            // set new baselayer
            this.baseLayer = newBaseLayer;

            // Increment viewRequestID since the baseLayer is 
            // changing. This is used by tiles to check if they should 
            // draw themselves.

            if(!this.allOverlays || this.baseLayer.visibility)

            this.maxExtent = this.baseLayer.maxExtent;

            //this.projection = this.baseLayer.projection.projCode;
            this.units = this.baseLayer.units;

            this.maxResolution = this.baseLayer.maxResolution;
            this.minResolution = this.baseLayer.minResolution;
            this.numZoomLevels = this.baseLayer.numZoomLevels;

            // recenter the map
            if (center != null)
                if (this.baseLayer.projection.projCode != oldBaseLayer.projection.projCode) 
                    var ct = new OpenLayers.Geometry.Point(center.lon, center.lat);

                    OpenLayers.Projection.transform(ct, oldBaseLayer.projection, this.baseLayer.projection);

                    center.lon = ct.x;
                    center.lat = ct.y;

                    //Dump other map parameters?
                    //this.units = this.baseLayer.units;
                    //this.maxExtent = this.baseLayer.maxExtent;
                    //this.maxResolution = this.baseLayer.maxResolution;
                    //this.numZoomLevels = this.baseLayer.numZoomLevels;
                    //this.projection = this.baseLayer.projection;

                    //Reproject any features. (Any way of doing this with one function call?)

                    var vecLayers = objMap.getLayersByClass('OpenLayers.Layer.Vector');

                    if (vecLayers != null)
                        for (i = 0; i < vecLayers.length; i++)
                            var arrFeat = vecLayers[i].features;

                            for (j = 0; j < arrFeat.length; j++)
                                arrFeat[j].geometry.transform(oldBaseLayer.projection, this.baseLayer.projection);

                            vecLayers[i].redraw(); //Seems to be necessary for marker.

                    //Need to reset maxExtent to redraw WMS layer.
                    //TODO: need to switch to version of layer that matches new projection, in order
                    //to avoid reprojecting.
                    var wmsLayers = this.getLayersByClass('OpenLayers.Layer.WMS');

                    if (wmsLayers != null)
                        for (i = 0; i < wmsLayers.length; i++)
                            //Get layer names.

                            wmsLayers[i].maxExtent = this.maxExtent;


                // new zoom level derived from old scale
                var newZoom = this.getZoomForResolution(newResolution || this.resolution, true);

                // zoom and force zoom change
                this.setCenter(center, newZoom, false, true);

            this.events.triggerEvent("changebaselayer", {
                layer: this.baseLayer


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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