I want to overlay some data whose projection is WGS-84 on Google map layer in OpenLayers. But I just can't make them in the right place. I did as follows:

map = new OpenLayers.Map('map', {           
        numZoomLevels: 20,
        projection: new OpenLayers.Projection("EPSG:900913"),
        displayProjection: new OpenLayers.Projection("EPSG: 4326")
googlelayer = new OpenLayers.Layer.Google("Google street", {sphericalMercator: true});
veclayer = new OpenLayers.Layer.Vector("vector", {
                                    projection: map.displayProjection
var geojson_format = new OpenLayers.Format.GeoJSON();

Though I have assigned veclayer in 4326 projection, but it is still interpreted as 900913, and the display coordination system is also 900913, though I set displayProjection to 4326. What mistake do I make?

5 Answers 5


I'm a big fan of "preFeatureInsert"....

var veclayer = new OpenLayers.Layer.Vector("vector", {
           projection: map.displayProjection,
           preFeatureInsert: function(feature) {
  • Aha, it works! Thank you very much. But I wonder what the property preFeatureInsert means, anyhow, I can't find it in the official API doc~
    – ChanDon
    Nov 18, 2011 at 11:06
  • 1
    As far as im concerned, it transforms the projections as defined, before the feature is inserted... Nice and generic, and no need for conversion functions etc. Nov 18, 2011 at 11:12

You have a space after the colon. Projection("EPSG: 4326") should actually be Projection("EPSG:4326"), no space before 4326.

  • Haha it really works! I mean for the display projection. However, the overlaid data is still not in the right place (the same wrong place as before). Any ideas?
    – ChanDon
    Nov 18, 2011 at 6:11
               map = new OpenLayers.Map('map',
                { numZoomLevels: 19,
                  units: 'm',
                  eventListeners: {"moveend": update_movend},
                  projection: new OpenLayers.Projection("EPSG:900913"),
                  displayProjection: new OpenLayers.Projection("EPSG:4326")


        OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:900913", OpenLayers.Layer.SphericalMercator.projectForward);
        OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:4326", OpenLayers.Layer.SphericalMercator.projectInverse);

        var layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
        var layerTah = new OpenLayers.Layer.OSM.Osmarender("Osmarender");

        var gphy = new OpenLayers.Layer.Google(
            "Google Physical",
                type: google.maps.MapTypeId.TERRAIN
//        gphy = map.projection;

        var gmap = new OpenLayers.Layer.Google(
            "Google Streets",
                numZoomLevels: 20,
        //gmap = map.projection;

        layerMapnik.projection = map.projection;
        layerTah.projection = map.projection;

        vectors = new OpenLayers.Layer.Vector("Vector Layer");

          var help_layer = new OpenLayers.Layer.Vector("Waypoints", {
             projection: map.displayProjection,
             strategies: [new OpenLayers.Strategy.Fixed()],

I posted my old code snippet. I remember that the clou is in the projections. addTransform should solve your problem. (proj4)

  • Thank you for your help. But it seems not to work
    – ChanDon
    Nov 18, 2011 at 11:07

You may fall there because you are looking for a slightly offset vector representation on Google Maps while it's fine on other base layers and transforming EPSG:4326 to EPSG:900913 or EPSG:3857 doesn't solve everything.

There is a bug on Google Maps that doesn't evaluate well the div size when initiating the OpenLayers Map object if it's not yet visible. So after the transform() & redraw() calls, you may need to do myMapObject.updateSize(); to let Google know the actual proportion of your map on screen.

If you are looking for a generic solution to transform layers from one projection to another, you could use this function:

var myMap = new OpenLayers.Map('mapDiv');

function mapBaseLayerChanged(evtObj) {
  var mapProj, baseProj, map_this, newBase;
  map_this = this;
  newBase = evtObj.layer;
  mapProj = (map_this.projection && map_this.projection instanceof OpenLayers.Projection) ?
            map_this.projection : new OpenLayers.Projection(map_this.projection);
  baseProj = newBase.projection;
  if (!(baseProj.equals(mapProj))) {
     var center, maxExt;
     center = map_this.getCenter().transform(mapProj, baseProj);
     maxExt = newBase.maxExtent;
     map_this.projection = baseProj;
     map_this.maxExtent = maxExt;
     map_this.setCenter(center, map_this.getZoom(), false, true);
     // Transforms all sub-layers
     for (var i = 0; i < map_this.layers.length; i++) {
        if (map_this.layers[i].isBaseLayer == false) {
           map_this.layers[i].addOptions({projection: baseProj}, true);
           // Transforms all features of the vectors
           for (var j = 0; j < map_this.layers[i].features.length; j++) {
              map_this.layers[i].features[j].geometry.transform(mapProj, baseProj);
     //Solves Google's problem (and mine at the same occasion)
myMap.events.register('changebaselayer', myMap, mapBaseLayerChanged);

Et voilà!


For Yahoo you can try these options:

  sphericalMercator: true,
  maxExtent:new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)

Your Answer

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

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