面标记
面标记用于在地图上绘制区域、多边形等面状要素。SDK 提供了简单易用的 API 来添加和管理面标记。
添加面标记
基础用法
javascript
// 添加一个简单的多边形
const featureId = sdk.addPolygon(
[
[
[116.3974, 39.9093], // 第一个点
[121.4737, 39.9093], // 第二个点
[121.4737, 31.2304], // 第三个点
[116.3974, 31.2304], // 第四个点
[116.3974, 39.9093], // 闭合多边形(回到起点)
],
],
{ name: "区域" }, // 属性
);
console.log("面标记ID:", featureId);带洞的多边形
javascript
// 添加带洞的多边形(外环 + 内环)
const featureId = sdk.addPolygon(
[
// 外环
[
[116.3974, 39.9093],
[121.4737, 39.9093],
[121.4737, 31.2304],
[116.3974, 31.2304],
[116.3974, 39.9093],
],
// 内环(洞)
[
[118.0, 36.0],
[119.0, 36.0],
[119.0, 35.0],
[118.0, 35.0],
[118.0, 36.0],
],
],
{ name: "带洞的区域" },
);自定义样式
javascript
// 添加带自定义样式的面
const featureId = sdk.addPolygon(
[
[
[116.3974, 39.9093],
[121.4737, 39.9093],
[121.4737, 31.2304],
[116.3974, 31.2304],
[116.3974, 39.9093],
],
],
{ name: "区域", type: "area" },
{
paint: {
"fill-color": "#ff0000", // 填充颜色
"fill-opacity": 0.5, // 填充透明度
"fill-outline-color": "#000000", // 轮廓颜色
"fill-pattern": null, // 填充图案(需要sprite)
},
}
);批量添加面标记
使用 GeoJSON 数据
javascript
// 添加多个面
const geojson = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[116.3974, 39.9093],
[121.4737, 39.9093],
[121.4737, 31.2304],
[116.3974, 31.2304],
[116.3974, 39.9093],
],
],
},
properties: { name: "区域1" },
},
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[113.2644, 23.1291],
[120.1551, 23.1291],
[120.1551, 30.2741],
[113.2644, 30.2741],
[113.2644, 23.1291],
],
],
},
properties: { name: "区域2" },
},
],
};
sdk.addGeoJSON("areas-source", geojson);
// 添加图层
sdk.addLayer({
id: "areas-layer",
source: "areas-source",
type: "fill",
paint: {
"fill-color": "#007bff",
"fill-opacity": 0.5,
},
});循环添加
javascript
const areas = [
{
name: "区域1",
coordinates: [
[
[116.3974, 39.9093],
[121.4737, 39.9093],
[121.4737, 31.2304],
[116.3974, 31.2304],
[116.3974, 39.9093],
],
],
},
{
name: "区域2",
coordinates: [
[
[113.2644, 23.1291],
[120.1551, 23.1291],
[120.1551, 30.2741],
[113.2644, 30.2741],
[113.2644, 23.1291],
],
],
},
];
areas.forEach((area) => {
sdk.addPolygon(
area.coordinates,
{ name: area.name },
{
paint: {
"fill-color": "#007bff",
"fill-opacity": 0.5,
},
}
);
});更新面标记
更新形状
javascript
// 获取要素并更新坐标
const feature = sdk.geoJSONManager.getFeature(featureId);
if (feature) {
// 更新坐标
feature.geometry.coordinates = [
[
[116.3974, 39.9093],
[121.4737, 39.9093],
[121.4737, 31.2304],
[116.3974, 31.2304],
[116.3974, 39.9093],
],
];
// 更新源数据
sdk.getSource("source-id").setData(updatedGeoJSON);
}更新样式
javascript
// 更新面样式
sdk.updateLayerStyle("polygon-layer", {
paint: {
"fill-color": "#ff0000",
"fill-opacity": 0.8,
},
});添加/删除顶点
javascript
// 添加顶点
function addVertexToPolygon(featureId, ringIndex, newVertex) {
const feature = sdk.geoJSONManager.getFeature(featureId);
if (feature && feature.geometry.type === "Polygon") {
const ring = feature.geometry.coordinates[ringIndex];
// 在倒数第二个位置插入(保持闭合)
ring.splice(-1, 0, newVertex);
sdk.getSource("source-id").setData(updatedGeoJSON);
}
}
// 删除顶点
function removeVertexFromPolygon(featureId, ringIndex, vertexIndex) {
const feature = sdk.geoJSONManager.getFeature(featureId);
if (feature && feature.geometry.type === "Polygon") {
const ring = feature.geometry.coordinates[ringIndex];
// 不能删除最后一个点(闭合点)
if (ring.length > 4 && vertexIndex < ring.length - 1) {
ring.splice(vertexIndex, 1);
sdk.getSource("source-id").setData(updatedGeoJSON);
}
}
}删除面标记
删除单个面
javascript
// 方法1:通过图层ID删除
sdk.removeLayer(featureId);
// 方法2:通过 GeoJSONManager 删除
sdk.geoJSONManager.removeFeature(featureId);删除多个面
javascript
const featureIds = ["polygon-1", "polygon-2", "polygon-3"];
featureIds.forEach((id) => {
sdk.removeLayer(id);
});清空所有面标记
javascript
// 删除整个图层
sdk.removeLayer("polygon-layer");
// 清空源数据
sdk.getSource("source-id").setData({
type: "FeatureCollection",
features: [],
});面标记交互
点击事件
javascript
// 监听面标记点击
sdk.on("click", "polygon-layer", (e) => {
const feature = e.features[0];
console.log("点击的面:", feature.properties);
// 显示弹窗
const popup = new navMap.Popup()
.setLngLat(e.lngLat)
.setHTML(`<h3>${feature.properties.name}</h3>`)
.addTo(sdk.map);
});悬停效果
javascript
// 鼠标悬停时高亮
sdk.on("mouseenter", "polygon-layer", (e) => {
sdk.getCanvas().style.cursor = "pointer";
// 改变样式
sdk.setPaintProperty("polygon-layer", "fill-color", "#ff0000");
sdk.setPaintProperty("polygon-layer", "fill-opacity", 0.8);
});
sdk.on("mouseleave", "polygon-layer", () => {
sdk.getCanvas().style.cursor = "";
// 恢复样式
sdk.setPaintProperty("polygon-layer", "fill-color", "#007bff");
sdk.setPaintProperty("polygon-layer", "fill-opacity", 0.5);
});使用 ClickManager
javascript
// 使用 ClickManager 简化点击处理
sdk.clickObj.clickPopup(
"polygon-layer",
(feature) => {
const area = calculateArea(feature.geometry.coordinates);
return `<h3>${feature.properties.name}</h3>
<p>面积: ${area.toFixed(2)} km²</p>`;
},
{
anchor: "bottom",
closeButton: true,
}
);样式配置
基础样式属性
javascript
sdk.addPolygon(
coordinates,
{ name: "区域" },
{
paint: {
"fill-color": "#ff0000", // 填充颜色
"fill-opacity": 0.5, // 填充透明度
"fill-outline-color": "#000000", // 轮廓颜色
"fill-pattern": null, // 填充图案
"fill-translate": [0, 0], // 平移
"fill-translate-anchor": "map", // 平移锚点
},
}
);轮廓线样式
javascript
// 添加轮廓线图层
sdk.addLayer({
id: "polygon-outline",
source: "polygon-source",
type: "line",
paint: {
"line-color": "#000000",
"line-width": 2,
"line-opacity": 1.0,
"line-dasharray": [2, 2], // 虚线轮廓
},
});动态样式
javascript
// 根据属性值动态设置颜色
sdk.addLayer({
id: "dynamic-polygons",
source: "polygons-source",
type: "fill",
paint: {
"fill-opacity": 0.5,
"fill-color": [
"case",
["==", ["get", "type"], "restricted"],
"#ff0000", // 限制区:红色
["==", ["get", "type"], "controlled"],
"#0000ff", // 管制区:蓝色
"#00ff00", // 其他:绿色
],
},
});根据缩放级别调整透明度
javascript
sdk.addLayer({
id: "zoom-polygons",
source: "polygons-source",
type: "fill",
paint: {
"fill-color": "#007bff",
"fill-opacity": [
"interpolate",
["linear"],
["zoom"],
5, 0.2, // 缩放级别5时透明度0.2
10, 0.5, // 缩放级别10时透明度0.5
15, 0.8, // 缩放级别15时透明度0.8
],
},
});填充图案
javascript
// 使用填充图案(需要先加载sprite)
sdk.addLayer({
id: "pattern-polygons",
source: "polygons-source",
type: "fill",
paint: {
"fill-pattern": "pattern-name", // sprite中的图案名称
"fill-opacity": 0.8,
},
});几何计算
计算面积
javascript
function calculateArea(coordinates) {
// 使用 turf.js 或其他几何计算库
const polygon = turf.polygon(coordinates);
return turf.area(polygon); // 返回平方米
}
// 使用示例
sdk.on("click", "polygon-layer", (e) => {
const feature = e.features[0];
const area = calculateArea(feature.geometry.coordinates);
console.log("面积:", area, "平方米");
});计算中心点
javascript
function getCentroid(coordinates) {
const polygon = turf.polygon(coordinates);
const centroid = turf.centroid(polygon);
return centroid.geometry.coordinates;
}
// 使用示例
const center = getCentroid(polygonCoordinates);
sdk.flyTo({
center: center,
zoom: 12,
});判断点是否在多边形内
javascript
function pointInPolygon(point, polygonCoordinates) {
const pt = turf.point(point);
const polygon = turf.polygon(polygonCoordinates);
return turf.booleanPointInPolygon(pt, polygon);
}
// 使用示例
const isInside = pointInPolygon([116.3974, 39.9093], polygonCoordinates);
console.log("点是否在多边形内:", isInside);完整示例
javascript
let sdk;
async function initMap() {
sdk = new navMap.MapSDK({
container: "map",
center: [116.39, 39.9],
zoom: 10,
});
sdk.on("loadComplete", () => {
setupPolygonMarkers();
});
}
function setupPolygonMarkers() {
// 1. 添加单个面
const polygonId = sdk.addPolygon(
[
[
[116.3974, 39.9093],
[121.4737, 39.9093],
[121.4737, 31.2304],
[116.3974, 31.2304],
[116.3974, 39.9093],
],
],
{ name: "区域", type: "area" },
{
paint: {
"fill-color": "#ff0000",
"fill-opacity": 0.5,
"fill-outline-color": "#000000",
},
}
);
// 2. 添加轮廓线
sdk.addLayer({
id: `${polygonId}-outline`,
source: polygonId,
type: "line",
paint: {
"line-color": "#000000",
"line-width": 2,
},
});
// 3. 批量添加面
const areas = [
{
name: "区域1",
coordinates: [
[
[116.3974, 39.9093],
[121.4737, 39.9093],
[121.4737, 31.2304],
[116.3974, 31.2304],
[116.3974, 39.9093],
],
],
},
];
areas.forEach((area) => {
sdk.addPolygon(
area.coordinates,
{ name: area.name, type: "area" },
{
paint: {
"fill-color": "#007bff",
"fill-opacity": 0.5,
},
}
);
});
// 4. 添加点击事件
sdk.clickObj.clickPopup(
polygonId,
(feature) => {
const area = calculateArea(feature.geometry.coordinates);
return `<h3>${feature.properties.name}</h3>
<p>类型: ${feature.properties.type}</p>
<p>面积: ${(area / 1000000).toFixed(2)} km²</p>`;
},
{
anchor: "bottom",
closeButton: true,
}
);
// 5. 添加悬停效果
sdk.on("mouseenter", polygonId, () => {
sdk.setPaintProperty(polygonId, "fill-color", "#00ff00");
sdk.setPaintProperty(polygonId, "fill-opacity", 0.8);
});
sdk.on("mouseleave", polygonId, () => {
sdk.setPaintProperty(polygonId, "fill-color", "#ff0000");
sdk.setPaintProperty(polygonId, "fill-opacity", 0.5);
});
}
initMap();注意事项
- 坐标顺序:坐标格式为
[经度, 纬度],注意顺序 - 闭合多边形:多边形的第一个点和最后一个点必须相同
- 环的方向:外环逆时针,内环(洞)顺时针
- 性能优化:大量面标记时考虑使用 LOD 配置
- 样式时机:确保在地图
loadComplete后再添加面标记 - 几何计算:复杂几何计算建议使用 turf.js 等专业库
