Skip to content

交互与事件

SDK 提供了丰富的地图交互功能和事件系统,支持鼠标、触摸、键盘等多种交互方式。

鼠标交互

点击事件

javascript
// 监听地图点击
sdk.on("click", (e) => {
  console.log("点击位置:", e.lngLat);
  console.log("点击的要素:", e.features);
  
  // 查询点击位置的要素
  const features = sdk.queryRenderedFeatures(e.point);
  console.log("查询到的要素:", features);
});

// 监听特定图层点击
sdk.on("click", "airport", (e) => {
  console.log("点击了机场图层:", e.features[0]);
});

双击事件

javascript
sdk.on("dblclick", (e) => {
  // 双击放大
  sdk.zoomIn();
});

右键菜单

javascript
sdk.on("contextmenu", (e) => {
  e.preventDefault();
  
  // 显示自定义右键菜单
  showContextMenu(e.lngLat);
});

鼠标悬停

javascript
// 鼠标进入
sdk.on("mouseenter", "airport", (e) => {
  // 改变鼠标样式
  sdk.getCanvas().style.cursor = "pointer";
});

// 鼠标离开
sdk.on("mouseleave", "airport", (e) => {
  sdk.getCanvas().style.cursor = "";
});

鼠标移动

javascript
sdk.on("mousemove", (e) => {
  // 实时显示鼠标位置
  updateMousePosition(e.lngLat);
});

拖拽交互

启用/禁用拖拽

javascript
// 禁用拖拽
sdk.dragPan.disable();

// 启用拖拽
sdk.dragPan.enable();

拖拽事件

javascript
sdk.on("dragstart", () => {
  console.log("开始拖拽");
});

sdk.on("drag", () => {
  console.log("拖拽中");
});

sdk.on("dragend", () => {
  console.log("拖拽结束");
});

缩放交互

鼠标滚轮缩放

javascript
// 禁用滚轮缩放
sdk.scrollZoom.disable();

// 启用滚轮缩放
sdk.scrollZoom.enable();

// 监听缩放事件
sdk.on("zoom", () => {
  console.log("缩放级别:", sdk.getZoom());
});

sdk.on("zoomstart", () => {
  console.log("开始缩放");
});

sdk.on("zoomend", () => {
  console.log("缩放结束");
});

双击缩放

javascript
// 禁用双击缩放
sdk.doubleClickZoom.disable();

// 启用双击缩放
sdk.doubleClickZoom.enable();

旋转交互

启用/禁用旋转

javascript
// 禁用旋转(右键拖拽)
sdk.dragRotate.disable();

// 启用旋转
sdk.dragRotate.enable();

旋转事件

javascript
sdk.on("rotate", () => {
  console.log("旋转角度:", sdk.getBearing());
});

sdk.on("rotatestart", () => {
  console.log("开始旋转");
});

sdk.on("rotateend", () => {
  console.log("旋转结束");
});

键盘交互

启用/禁用键盘

javascript
// 禁用键盘控制
sdk.keyboard.disable();

// 启用键盘控制
sdk.keyboard.enable();

键盘事件

SDK 默认支持以下键盘快捷键:

  • + / -:缩放
  • / / / :平移
  • Shift + ← / Shift + →:旋转
javascript
// 监听键盘事件
document.addEventListener("keydown", (e) => {
  if (e.key === "+" || e.key === "=") {
    sdk.zoomIn();
  } else if (e.key === "-") {
    sdk.zoomOut();
  }
});

触摸交互(移动端)

触摸事件

javascript
sdk.on("touchstart", (e) => {
  console.log("触摸开始");
});

sdk.on("touchmove", (e) => {
  console.log("触摸移动");
});

sdk.on("touchend", (e) => {
  console.log("触摸结束");
});

捏合缩放

javascript
sdk.on("touchzoom", () => {
  console.log("捏合缩放");
});

要素查询

查询渲染的要素

javascript
// 查询点击位置的要素
sdk.on("click", (e) => {
  const features = sdk.queryRenderedFeatures(e.point);
  console.log("查询到的要素:", features);
});

// 查询指定图层的要素
const features = sdk.queryRenderedFeatures(e.point, {
  layers: ["airport", "airline"],
});

// 查询指定区域的要素
const boxFeatures = sdk.queryRenderedFeatures([
  [x1, y1],
  [x2, y2],
]);

查询源数据

javascript
// 查询源中的所有要素
const sourceFeatures = sdk.querySourceFeatures("airport-source", {
  sourceLayer: "airport",
  filter: ["==", "type", "civil"],
});

事件管理

添加事件监听

javascript
// 添加事件监听
const handler = (e) => {
  console.log("事件触发:", e);
};

sdk.on("click", handler);

移除事件监听

javascript
// 移除特定监听器
sdk.off("click", handler);

// 移除所有监听器
sdk.off("click");

一次性事件监听

javascript
// 只监听一次
sdk.once("loadComplete", () => {
  console.log("地图加载完成(只执行一次)");
});

自定义交互

使用 ClickManager

javascript
// 点击时显示弹窗
sdk.clickObj.clickPopup(
  "airport",
  (feature) => {
    return `<h3>${feature.properties.name}</h3>`;
  },
  {
    anchor: "bottom",
    closeButton: true,
  }
);

使用 HoverManager

javascript
// 悬停时显示信息
sdk.hover.hoverPopup(
  "airport",
  (feature) => {
    return `<div>${feature.properties.name}</div>`;
  },
  {
    anchor: "top",
  }
);

使用 SelectFeature

javascript
// 启用要素选择
sdk.selector.enable({
  onSelect: (feature, properties) => {
    console.log("选中的要素:", feature);
  },
  isHighlight: true, // 高亮选中要素
  isMultiSelect: false, // 是否支持多选
});

// 禁用要素选择
sdk.selector.disable();

// 清除选择
sdk.selector.clearSelection();

完整示例

javascript
let sdk;

async function initMap() {
  sdk = new navMap.MapSDK({
    container: "map",
    center: [116.39, 39.9],
    zoom: 10,
  });

  sdk.on("loadComplete", () => {
    setupInteractions();
  });
}

function setupInteractions() {
  // 1. 点击查询要素
  sdk.on("click", (e) => {
    const features = sdk.queryRenderedFeatures(e.point, {
      layers: ["airport"],
    });
    
    if (features.length > 0) {
      const feature = features[0];
      showFeatureInfo(feature);
    }
  });

  // 2. 悬停高亮
  sdk.on("mouseenter", "airport", (e) => {
    sdk.getCanvas().style.cursor = "pointer";
    highlightFeature(e.features[0]);
  });

  sdk.on("mouseleave", "airport", () => {
    sdk.getCanvas().style.cursor = "";
    clearHighlight();
  });

  // 3. 双击缩放
  sdk.on("dblclick", (e) => {
    sdk.flyTo({
      center: e.lngLat,
      zoom: sdk.getZoom() + 1,
      duration: 500,
    });
  });

  // 4. 右键菜单
  sdk.on("contextmenu", (e) => {
    e.preventDefault();
    showContextMenu(e.lngLat);
  });

  // 5. 缩放时调整图层
  sdk.on("zoom", () => {
    const zoom = sdk.getZoom();
    if (zoom > 12) {
      sdk.showLayers(["detail-layer"]);
    } else {
      sdk.hideLayers(["detail-layer"]);
    }
  });

  // 6. 使用选择管理器
  sdk.selector.enable({
    onSelect: (feature) => {
      console.log("选中要素:", feature);
    },
    isHighlight: true,
  });
}

function showFeatureInfo(feature) {
  const popup = new navMap.Popup()
    .setLngLat(feature.geometry.coordinates)
    .setHTML(`<h3>${feature.properties.name}</h3>`)
    .addTo(sdk.map);
}

initMap();

注意事项

  1. 事件顺序:确保在地图 loadComplete 后再添加事件监听
  2. 性能优化:避免在频繁触发的事件(如 mousemove)中执行复杂操作
  3. 事件清理:页面卸载前记得移除事件监听,避免内存泄漏
  4. 移动端适配:移动端优先使用触摸事件,而非鼠标事件