1

I am trying to add an xyz source tile layer to OpenLayers v8.1.

The source URI for the tiles is the Chinese autonavi / amap provider.

http://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}

When overlaid to the default OSM layer the amap tile layer appears shifted.

enter image description here

The shift of roughly 500m east, and 200m south seems to indicate that the autonavi tiles use a webmercator projection with a pseudo-datum like GCJ-02

Also referenced in this PROJ issue.

Does anybody know how to apply the datum shift to a web mercator projection for this XYZ/Tile layer?

I've created a codepen here.

const amap_layer = new ol.layer.Tile({
  opacity: 0.5,
  source: new ol.source.XYZ({
    url:
      "http://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
  })
});

new ol.Map({
  target: "OL",
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    }),
    amap_layer
  ],
  view: new ol.View({
    center: ol.proj.fromLonLat([120.3, 30.3]),
    zoom: 13
  }),
  controls: [
    new ol.control.Zoom(),
    new ol.control.ScaleLine({
      minWidth: 64,
      units: "metric"
    })
  ]
});
2
  • You need to specify the projection in the source codepen.io/mike-000/pen/PoVzgEX
    – Mike
    Commented Nov 1, 2023 at 19:02
  • If I set the Baidu project the map is completely misaligned. I don't really know what the AMAP projection. It's like web mercator with a GCJ-02 datum. @Mike if I open your codepen fork the amap is completely misaligned not just slightly shifted. Commented Nov 1, 2023 at 19:25

1 Answer 1

2

The Baidu layer will align with OSM (but not using https) by changing var y = tileCoord[2]; to var y = -tileCoord[2] - 1; (see https://github.com/openlayers/openlayers/issues/10374)

For the amap layer you need a mercator projection based on the GCJ02 transforms - I found a transform between GCJ02 lon/lat values and EPSG:4326 and EPSG:3857. The normal EPSG:4326 to EPSG:3857 transforms can then be applied to create a GCJ02 mercator projection from the GCJ02 lon/lat projection:

import {GCJ02} from "https://esm.sh/ol-proj-ch";

const gcj02Mercator = new ol.proj.Projection({
  code: "gcj02",
  extent: ol.proj.get('EPSG:3857').getExtent(),
  units: "m"
});

const ll2merc = ol.proj.getTransform('EPSG:4326', 'EPSG:3857');
const merc2ll = ol.proj.getTransform('EPSG:3857', 'EPSG:4326');

ol.proj.addProjection(gcj02Mercator);

ol.proj.addCoordinateTransforms(
  "EPSG:4326",
  gcj02Mercator,
  (x) => ll2merc(GCJ02.fromEPSG4326(x)),
  (x) => GCJ02.toEPSG4326(merc2ll(x))
);

ol.proj.addCoordinateTransforms(
  "EPSG:3857",
  gcj02Mercator,
  (x) => ll2merc(GCJ02.fromEPSG3857(x)),
  (x) => GCJ02.toEPSG3857(merc2ll(x))
);

const amap_layer = new ol.layer.Tile({
  opacity: 0.5,
  source: new ol.source.XYZ({
    projection: 'gcj02',
    url:
      "http://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
  })
});

Working demo with layer switcher added http://mikenunn.x10host.com/demo/baidu.html

1
  • Thanks so much for doing this. This works perfectly. I have updated my codepen to reflect the changes. Commented Nov 2, 2023 at 11:20

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.