首页 / 浏览问题 / WebGIS / 问题详情
Canvas如何在iclient for leaflet调用地图上绘制
11EXP 2023年09月07日
我希望在iclient for leaflet调用的地图上用canvas绘制行政区的边界,我通过获取geojson数据中的坐标绘制,但不知道iclient for leaflet提供的api中如何用canvas 对地图进行交互,使我能够将想绘制的图层绘制在地图上。求认真解答,真的困扰了很久了。

1个回答

您好,在leaflet调用的地图上用canvas绘制行政区的边界,可以通过以下步骤进行:

1、导入正确的库文件

2、创建一个基本地图

3、通过geojson数据绘制行政区边界:

// 获取行政区边界的GeoJSON数据
// 假设 geojsonCoordinates 是你获取到的行政区边界坐标数组
var geojsonCoordinates = [
  [[116.1919, 39.957]],
  [[116.1919, 39.949]],
  // ...
];

// 创建一个 CanvasLayer
var canvasLayer = L.canvasLayer();

// 自定义绘制函数
function customDrawFunc(canvasOverlay, params) {
  var ctx = params.canvas.getContext('2d');

  // 设置绘制样式
  ctx.lineWidth = 2;
  ctx.strokeStyle = '#f00';

  // 开始绘制路径
  ctx.beginPath();

  // 遍历坐标数组并绘制边界
  for (var i = 0; i < geojsonCoordinates.length; i++) {
    var coordinates = geojsonCoordinates[i];

    for (var j = 0; j < coordinates.length; j++) {
      var coord = coordinates[j];
      if (j === 0) {
        ctx.moveTo(coord[0], coord[1]);
      } else {
        ctx.lineTo(coord[0], coord[1]);
      }
    }
  }

  // 结束绘制路径
  ctx.stroke();
}

// 设置自定义绘制函数
canvasLayer.draw = customDrawFunc;

// 添加 CanvasLayer 到地图上
canvasLayer.addTo(map);

请注意,该代码只提供了通过geojson数据绘制边界的基础框架,具体的地理数据需要根据实际情况进行获取和处理。此外,您需要根据自己的需求对绘制的样式和绘制函数进行进一步的调整。

希望能帮助到您!

1,045EXP 2023年09月07日
是否需要引入文件?需要哪些。我这里报错canvas.js:85  Uncaught TypeError: L.canvasLayer is not a function
    at canvas.js:85:21求解答

您好,用leaflet和canvas进行开发,需要引入正确的leaflet和canvas库文件,您代码报错的原因是未引入正确的canvas库文件:

1、本地引用需要下载部署js文件,适用于需要离线访问、特定版本管理或定制化需求较高的场景,下载地址为:leaflet-canvaslayer-field - npm (npmjs.com)

2、在线引用适合于简化部署和联网开发的场景,在线引用语句为:<script src="fastly.jsdelivr.net/npm/leaflet-canvaslayer-field/dist/leaflet.canvaslayer.field.min.js">

希望对您有所帮助!

引入了在线js文件后,L.canvasLayer()依旧会报错,是没有这个方法吗?还是引入版本的问题

不好意思,我之前回答的在线引用地址被自动注释掉了前缀,完整的在线引用语句为:<script src="https://fastly.jsdelivr.net/npm/leaflet-canvaslayer-field/dist/leaflet.canvaslayer.field.min.js">,我自己测试是没问题的,引用这个L.canvasLayer()不会报错。但是建议您还是本地下载canvas引用包,方便引用canvas的样式文件。

非常感谢您的回复!但是我经过测试,根据您的代码提示以及引入,尝试在地图图层上用canvas进行绘制,并没有得到我想要的结果。后台没有报错,但是在地图上没有看到绘制的图层,DOM里也没有看到添加。我找不出问题的所在。请您帮我指出代码的问题,为什么看不到绘制的图层在地图上。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Canvas 绘制示例</title>
    <!-- 引入 Leaflet CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.css" />
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.js"></script>
    <script type="text/javascript" src="https://iclient.supermap.io/dist/leaflet/iclient-leaflet.js"></script>
    <!-- canvas -->
    <script src="https://fastly.jsdelivr.net/npm/leaflet-canvaslayer-field/dist/leaflet.canvaslayer.field.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.css" />
    <!-- 样式定义 -->
    <style>
        /* 设置地图容器的大小 */
        #map {
            width: 800px;
            height: 600px;
        }
    </style>
</head>

<body>
    <!-- 创建地图容器 -->
    <div id="map"></div>

    <script>
        // 创建 Leaflet 地图实例
        var map = L.map('map', {
            center: [39.953, 116.195], // 设置地图中心坐标
            zoom: 12, // 设置缩放级别
            crs: L.supermap.CRS.TianDiTu_Mercator
        });

        // 创建矢量图层对象
        var vectorLayer = new L.supermap.TiandituTileLayer({
            layerType: 'vec',
            key: '1d109683f4d84198e37a38c442d68311'
        }).addTo(map);

        // 创建 CanvasLayer
        var canvasLayer = L.canvasLayer();

        // 添加多个点坐标
        var geojsonCoordinates = [
            [[116.1919, 39.957]],
            [[116.1919, 39.949]],
            [[116.195, 39.953]], // 新点
            [[116.198, 39.951]], // 新点
            // ... 可以继续添加更多点坐标
        ];

        // 自定义绘制函数
        function customDrawFunc(canvasOverlay, params) {
            var ctx = params.canvas.getContext('2d');

            // 设置绘制样式
            ctx.lineWidth = 4;
            ctx.strokeStyle = 'black';

            // 开始绘制路径
            ctx.beginPath();

            // 遍历坐标数组并绘制边界
            for (var i = 0; i < geojsonCoordinates.length; i++) {
                var coordinates = geojsonCoordinates[i];

                for (var j = 0; j < coordinates.length; j++) {
                    var coord = coordinates[j];
                    if (j === 0) {
                        ctx.moveTo(coord[0], coord[1]);
                    } else {
                        ctx.lineTo(coord[0], coord[1]);
                    }
                }
            }

            // 结束绘制路径
            ctx.stroke();
        }

        // 设置自定义绘制函数
        canvasLayer.draw = customDrawFunc;

        // 添加 CanvasLayer 到地图上
        canvasLayer.addTo(map);
    </script>
</body>

</html>

如果您有可以根据经纬度在地图上绘制的结果,请发送给我。非常感激!

您好,您的代码引用leaflet.canvaslayer.field插件进行绘制,没有绘制出结果可能是在线引用有问题,可以试试本地部署引用最新版插件,如果您只想根据经纬度在地图上进行绘制的话,可以采用以下在线引用能实现的实例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>leaflet绘制示例</title>
    <!-- 引入 Leaflet CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.css" />
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.js"></script>
    <script type="text/javascript" src="https://iclient.supermap.io/dist/leaflet/iclient-leaflet.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.css" />
    <!-- 样式定义 -->
    <style>
        /* 设置地图容器的大小 */
        #map {
            width: 800px;
            height: 600px;
        }
    </style>
</head>

<body>
    <!-- 创建地图容器 -->
    <div id="map"></div>

    <script>
        // 创建 Leaflet 地图实例
        var map = L.map('map', {
            center: [39.953, 116.195], // 设置地图中心坐标
            zoom: 12, // 设置缩放级别
            crs: L.supermap.CRS.TianDiTu_Mercator
        });

        // 创建矢量图层对象
        var vectorLayer = new L.supermap.TiandituTileLayer({
            layerType: 'vec',
            key: '1d109683f4d84198e37a38c442d68311'
        }).addTo(map);
        var latlngs = [
      [39.957, 116.1919],
      [39.949, 116.1919],
      [39.953, 116.195],
      [39.951, 116.198]
    ];
    var polyline = L.polyline(latlngs, { color: 'red' }).addTo(map);
    // 可选:添加起点和终点的标记
    L.marker(latlngs[0]).addTo(map); // 起点
    L.marker(latlngs[latlngs.length - 1]).addTo(map);// 终点

    map.fitBounds(polyline.getBounds());//调整地图视图以适应绘制的路径
    </script>
</body>

</html>

运行结果如下:

您的方法常用于绘制路径,我希望获取geojson数据中的经纬度,geojson数据中存放一个行政区的边界数据,利用canvas绘制行政区的边界图层添加在iclient for leaflet地图上,按照您的方法canvas绘制没有在地图上进行显示。

您好,之前给您回答的绘制行政区方法只是简单的逻辑框架,需要自己进一步细化修改,以下是我测试的在线引用的完整代码示例:

<!DOCTYPE html>
<html>
<head>
    <title>绘制行政区边界</title>
    <!-- 引入 Leaflet 库 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.7.1/dist/leaflet.css" />
    <script src="https://cdn.jsdelivr.net/npm/leaflet@1.7.1/dist/leaflet.js"></script>
</head>
<body>
    <div id="map" style="width: 800px; height: 600px;"></div>
    <script>
        // 创建 Leaflet 地图对象
        var map = L.map('map').setView([31.22, 121.48], 12);
        // 添加底图图层
        L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
            attribution: '© OpenStreetMap contributors'
        }).addTo(map);

        // 定义 GeoJSON 数据
        var geojsonData = {
            "type": "FeatureCollection",
            "features": [{
                "type": "Feature",
                "properties": {},
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [[[121.475,31.248],[121.477,31.246],[121.479,31.245],[121.481,31.245],[121.483,31.247],[121.484,31.249],[121.484,31.251],[121.482,31.252],[121.480,31.253],[121.478,31.252],[121.476,31.250],[121.475,31.248]]]
                }
            }]
        };

        // 创建 GeoJSON 图层
        var geojsonLayer = L.geoJSON(geojsonData);
        geojsonLayer.addTo(map);

        // 创建 Canvas 图层
        var canvasLayer = L.canvas();
        canvasLayer.addTo(map);

        // 获取 Canvas 的上下文对象
        var ctx = canvasLayer.getRenderer().getContext();

        // 设置绘制样式
        ctx.strokeStyle = "red";
        ctx.lineWidth = 2;

        // 遍历 GeoJSON 数据的每个特征
        geojsonData.features.forEach(function(feature) {
            // 获取特征的坐标
            var coordinates = feature.geometry.coordinates;
            
            // 绘制边界
            coordinates.forEach(function(coords) {
                coords.forEach(function(coord) {
                    var latLng = L.GeoJSON.coordsToLatLng(coord);
                    var point = map.latLngToContainerPoint(latLng);
                    
                    if (coord === coordinates[0][0]) {
                        ctx.moveTo(point.x, point.y);
                    } else {
                        ctx.lineTo(point.x, point.y);
                    }
                });
            });
        });

        // 绘制边界线
        ctx.stroke();
    </script>
</body>
</html>

运行结果如下:

您可以根据需要部署最新版的本地引用库,SuperMap iClient for Leaflet下载地址为:下载 (supermap.io)

希望对您有所帮助!

已经解决了,非常感谢!
您好老师,在地图上绘制的图层用什么方式清除呢?求清除图层的代码,感谢!

您好,要清除地图上的图层,可以使用removeLayer方法,示例代码如下:

map.removeLayer(layer); // 其中,layer是要从地图上移除的图层对象

希望对您有所帮助!

...