You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi FMX集成OpenStreetMap实现附近门店地图功能遇阻求助

我来帮你解决这个Delphi FMX集成OpenStreetMap的问题,你遇到的情况其实挺常见的,咱们一步步来排查和解决:

一、先解决你用TWebBrowser+OpenLayers的问题

你的自定义HTML没生效,大概率是这几个原因:

  • 旧的OpenLayers脚本用了HTTP协议,现在很多平台会阻止不安全的资源加载
  • 代码里的[Lng]和[Lat]是占位符,没有替换成实际的经纬度数值
  • FMX的TWebBrowser在不同平台有兼容性配置要求

修复后的HTML和Delphi代码

首先把OpenLayers的脚本换成HTTPS的CDN地址,替换占位符,同时优化HTML的样式避免留白:

procedure TForm1.FormCreate(Sender: TObject);
var
  LHTML: string;
begin
  // 注意替换成你需要的经纬度,这里用北京的坐标示例
  LHTML := '<html>' +
           '<head>' +
           '  <meta name="viewport" content="initial-scale=1.0, user-scalable=yes" />' +
           '  <!-- 解决Windows下IE内核兼容性问题 -->' +
           '  <meta http-equiv="X-UA-Compatible" content="IE=edge" />' +
           '  <!-- 使用HTTPS的OpenLayers CDN -->' +
           '  <script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.13.1/OpenLayers.js"></script>' +
           '  <script type="text/javascript">' +
           '    function initialize() {' +
           '      map = new OpenLayers.Map("map_canvas");' +
           '      map.addLayer(new OpenLayers.Layer.OSM());' +
           '      // 替换为实际的经纬度' +
           '      var lonLat = new OpenLayers.LonLat(116.4074, 39.9042)' +
           '        .transform(' +
           '          new OpenLayers.Projection("EPSG:4326"),' +
           '          map.getProjectionObject()' +
           '        );' +
           '      var zoom = 16;' +
           '      var markers = new OpenLayers.Layer.Markers("Markers");' +
           '      map.addLayer(markers);' +
           '      markers.addMarker(new OpenLayers.Marker(lonLat));' +
           '      map.setCenter(lonLat, zoom);' +
           '    }' +
           '  </script>' +
           '</head>' +
           '<body onload="initialize()" style="margin:0; padding:0;">' +
           '  <div id="map_canvas" style="width:100%; height:100%;"></div>' +
           '</body>' +
           '</html>';
  // 用NavigateToString加载本地HTML,而不是Navigate到外部网址
  WebBrowser1.NavigateToString(LHTML);
end;

各平台额外配置

  • Windows:确保IE的文档模式是Edge,上面的HTML已经加了<meta http-equiv="X-UA-Compatible" content="IE=edge" />,解决旧IE不兼容的问题
  • Android:在AndroidManifest.xml里添加INTERNET权限:<uses-permission android:name="android.permission.INTERNET" />
  • iOS:在Info.plist里添加App Transport Security设置,允许加载HTTPS资源(如果用了HTTP资源,需要设置NSAllowsArbitraryLoads为YES,但更推荐全用HTTPS)

二、更优方案:用FMX原生TMapView集成OSM

如果不想用WebBrowser的兼容性问题,Delphi从10.2开始提供了TMapView组件,可以直接自定义瓦片源为OpenStreetMap,体验更原生:

uses
  FMX.Maps, FMX.Maps.Types;

procedure TForm1.FormCreate(Sender: TObject);
var
  LTileSource: TOSMTileSource;
  LMarker: TMapMarker;
begin
  // 创建OpenStreetMap瓦片源
  LTileSource := TOSMTileSource.Create;
  try
    MapView1.MapType := TMapType.Custom;
    MapView1.CustomTileSource := LTileSource;
    // 设置初始中心坐标和缩放级别
    MapView1.Center := TMapCoordinate.Create(39.9042, 116.4074);
    MapView1.Zoom := 16;
    // 添加门店标记
    LMarker := TMapMarker.Create(MapView1);
    LMarker.Position := TMapCoordinate.Create(39.9042, 116.4074);
    LMarker.Title := '我的门店';
    LMarker.Snippet := '这里是门店详情';
    MapView1.AddMarker(LMarker);
  finally
    LTileSource.Free;
  end;
end;

这个方案的好处是:

  • 原生组件,性能比WebBrowser好
  • 自动适配不同平台的UI风格
  • 不需要处理HTML和JS的兼容性问题

三、添加多个门店标记

如果要显示多个附近门店,不管用哪种方案,都可以循环添加标记:

WebBrowser方案的JS修改

把添加标记的部分改成循环:

// 示例门店数据,格式为[经度, 纬度]
var stores = [[116.4074, 39.9042], [116.4100, 39.9050], [116.4050, 39.9030]];
for(var i=0; i<stores.length; i++){
  var storeLonLat = new OpenLayers.LonLat(stores[i][0], stores[i][1])
    .transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
  markers.addMarker(new OpenLayers.Marker(storeLonLat));
}

TMapView方案的Delphi代码修改

循环创建并添加标记:

// 示例门店坐标列表
var Stores: array of TMapCoordinate = [
  TMapCoordinate.Create(39.9042, 116.4074),
  TMapCoordinate.Create(39.9050, 116.4100),
  TMapCoordinate.Create(39.9030, 116.4050)
];
for var Index := 0 to High(Stores) do
begin
  var LMarker := TMapMarker.Create(MapView1);
  LMarker.Position := Stores[Index];
  LMarker.Title := '门店' + IntToStr(Index+1);
  MapView1.AddMarker(LMarker);
end;

这样就能显示多个门店标记了。

内容的提问来源于stack exchange,提问作者Mahmoud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 09:59:16