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

如何在无地图API的情况下将经纬度投影到HTML Canvas绘制图形

经纬度转Canvas坐标的正确实现方法

我从谷歌地图获取了一个近似方形建筑的经纬度数据:

[
    [26.680863912523936, -80.1179154920308],
    [26.680835153186823, -80.11685065504936],
    [26.679931626985823, -80.11687479493054],
    [26.679979559590112, -80.11796108958417]
]

尝试用全局投影方法(将整个地球经纬度范围映射到Canvas)失败了,转换后的屏幕坐标差值极小,无法正常绘制方形:

function projectLatLongToScreen(latitude, longitude) {
        const scaleFactorX = canvas.width / 360;
        const scaleFactorY = canvas.height / 180;

        const x = (longitude + 180) * scaleFactorX;
        const y = canvas.height - (latitude + 90) * scaleFactorY;
        
        return { x, y };
}

问题原因

原方法的缩放因子基于整个地球的经纬度范围(经度±180°,纬度±90°)计算,但目标坐标属于极小的局部区域,经纬度差值不到0.001°,用全局缩放后,屏幕坐标的差异自然微乎其微。

解决方案:局部区域映射

通过提取坐标的经纬度极值,将小范围的地理坐标映射到整个Canvas(可添加边距避免内容贴边),具体步骤:

  1. 找出所有点的最小/最大经度、纬度
  2. 计算经度范围(maxLon - minLon)和纬度范围(maxLat - minLat)
  3. 根据Canvas尺寸和边距,计算局部缩放因子
  4. 将每个点的经纬度平移到以(minLon, minLat)为原点的坐标系,再缩放后映射到Canvas

修改后的完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Manual Projection</title>
    <style>
        canvas {
            border: 1px solid #000;
        }
    </style>
</head>
<body>

<canvas id="myCanvas" width="800" height="600"></canvas>

<script>
    const coordinates = [
        { latitude: 26.680863912523936, longitude: -80.1179154920308 },
        { latitude: 26.680835153186823, longitude: -80.11685065504936 },
        { latitude: 26.679931626985823, longitude: -80.11687479493054 },
        { latitude: 26.679979559590112, longitude: -80.11796108958417 }
    ];

    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    const padding = 50; // 画布边距

    // 计算经纬度的极值
    const lats = coordinates.map(c => c.latitude);
    const lons = coordinates.map(c => c.longitude);
    const minLat = Math.min(...lats);
    const maxLat = Math.max(...lats);
    const minLon = Math.min(...lons);
    const maxLon = Math.max(...lons);

    // 计算局部缩放因子
    const lonRange = maxLon - minLon;
    const latRange = maxLat - minLat;
    const scaleX = (canvas.width - 2 * padding) / lonRange;
    const scaleY = (canvas.height - 2 * padding) / latRange;
    // 取较小的缩放因子,保证图形完整显示在画布内
    const scale = Math.min(scaleX, scaleY);

    // 经纬度转Canvas坐标的函数
    function projectLatLongToScreen(latitude, longitude) {
        // 平移到局部原点,再缩放,最后加上边距
        const x = padding + (longitude - minLon) * scale;
        // 纬度是北正南负,Canvas是上北下南,所以需要翻转
        const y = padding + (maxLat - latitude) * scale;
        return { x, y };
    }
        
    // 绘制多边形和点
    ctx.beginPath();
    coordinates.forEach((coord, index) => {
        const screenCoord = projectLatLongToScreen(coord.latitude, coord.longitude);
        if (index === 0) {
            ctx.moveTo(screenCoord.x, screenCoord.y);
        } else {
            ctx.lineTo(screenCoord.x, screenCoord.y);
        }
        // 绘制顶点
        ctx.beginPath();
        ctx.arc(screenCoord.x, screenCoord.y, 5, 0, 2 * Math.PI);
        ctx.fillStyle = 'red';
        ctx.fill();
    });
    // 闭合多边形
    ctx.closePath();
    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 2;
    ctx.stroke();
</script>

</body>
</html>

代码说明

  • 增加padding变量,避免图形贴在画布边缘
  • 通过计算局部经纬度范围,得到合适的缩放因子,确保小范围坐标被放大到整个画布
  • 处理了Canvas坐标系与地理坐标系的y轴方向差异(Canvas从上到下y值递增,地理纬度从南到北递增)
  • 同时绘制顶点和多边形边框,更直观展示方形结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 21:07:34