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

能否在2D场景下为ArcGIS SketchViewModel添加Tooltip?

2D ArcGIS地图自定义轻量级Tooltip实现思路(React项目)

你需要的是类似下图的轻量级Tooltip效果:
Tooltip示例

下面是几种可行的实现方案,适配React项目场景:

方案一:原生DOM+地图鼠标事件监听

这是最灵活的方案,完全自定义Tooltip的样式和行为:

    1. 在React组件中创建一个绝对定位的Tooltip容器,默认隐藏
    1. 给ArcGIS MapView绑定pointer-move和pointer-out事件,通过hitTest检测鼠标下的图形
    1. 命中图形时,提取属性内容并更新Tooltip的位置和显示状态;未命中时隐藏Tooltip

React组件代码片段

import React, { useEffect, useRef, useState } from 'react';
import Map from '@arcgis/core/Map';
import MapView from '@arcgis/core/views/MapView';

const MapWithCustomTooltip = () => {
  const mapContainerRef = useRef(null);
  const [tooltipState, setTooltipState] = useState({
    visible: false,
    content: '',
    position: { left: 0, top: 0 }
  });

  useEffect(() => {
    if (!mapContainerRef.current) return;

    // 初始化地图和视图
    const map = new Map({ basemap: 'streets' });
    const view = new MapView({
      container: mapContainerRef.current,
      map: map,
      center: [-118.805, 34.027],
      zoom: 13
    });

    // 监听鼠标移动事件
    const handlePointerMove = async (event) => {
      // 只检测目标图层的图形(可选,优化性能)
      const hitResult = await view.hitTest(event, { include: [yourTargetLayer] });
      const targetGraphic = hitResult.results.find(res => res.graphic);

      if (targetGraphic) {
        // 从图形属性中拼接Tooltip内容
        const content = `
          <div>名称:${targetGraphic.attributes.name}</div>
          <div>编号:${targetGraphic.attributes.id}</div>
          <div>类型:${targetGraphic.attributes.type}</div>
        `;
        // 将地图坐标转换为屏幕坐标
        const screenPoint = view.toScreen(event.mapPoint);
        setTooltipState({
          visible: true,
          content,
          position: {
            left: `${screenPoint.x + 12}px`,
            top: `${screenPoint.y + 12}px`
          }
        });
      } else {
        setTooltipState(prev => ({ ...prev, visible: false }));
      }
    };

    // 鼠标移出地图时隐藏Tooltip
    const handlePointerOut = () => {
      setTooltipState(prev => ({ ...prev, visible: false }));
    };

    view.on('pointer-move', handlePointerMove);
    view.on('pointer-out', handlePointerOut);

    return () => {
      view.destroy();
    };
  }, []);

  return (
    <div style={{ position: 'relative', width: '100%', height: '90vh' }}>
      {/* ArcGIS地图容器 */}
      <div ref={mapContainerRef}></div>
      {/* 自定义Tooltip */}
      {tooltipState.visible && (
        <div
          style={{
            position: 'absolute',
            ...tooltipState.position,
            background: '#ffffff',
            padding: '8px 14px',
            borderRadius: '4px',
            boxShadow: '0 2px 8px rgba(0,0,0,0.18)',
            fontSize: '14px',
            zIndex: 9999,
            pointerEvents: 'none' // 避免拦截地图鼠标事件
          }}
          dangerouslySetInnerHTML={{ __html: tooltipState.content }}
        />
      )}
    </div>
  );
};

export default MapWithCustomTooltip;

关键优化点

  • 给Tooltip设置pointerEvents: none,防止干扰地图交互
  • 通过hitTest的include参数指定目标图层,减少检测范围提升性能
  • 可添加节流函数限制pointer-move事件触发频率,避免频繁更新DOM

方案二:基于ArcGIS View UI组件扩展

利用ArcGIS内置的UI组件体系,无需自己处理层级问题:

    1. 创建Tooltip DOM元素,设置基础样式
    1. 通过view.ui.add(tooltipEl, 'manual')将其添加到地图视图
    1. 在鼠标事件中更新Tooltip的位置和内容(使用view.ui.move()调整位置)

核心代码片段

// 在useEffect中初始化Tooltip元素
const tooltipEl = document.createElement('div');
tooltipEl.style.cssText = `
  background: white;
  padding: 8px 12px;
  border-radius: 4px;
  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
  display: none;
`;
view.ui.add(tooltipEl, 'manual');

// 在pointer-move事件中更新
if (targetGraphic) {
  tooltipEl.innerHTML = `名称:${targetGraphic.attributes.name}`;
  const screenPoint = view.toScreen(event.mapPoint);
  view.ui.move(tooltipEl, {
    position: 'manual',
    x: screenPoint.x + 10,
    y: screenPoint.y + 10
  });
  tooltipEl.style.display = 'block';
} else {
  tooltipEl.style.display = 'none';
}

方案三:结合React生态Tooltip库

如果项目已使用react-tooltip等库,可通过坐标转换实现联动:

    1. 安装并引入React Tooltip组件
    1. 在鼠标命中图形时,调用Tooltip的open方法,传入屏幕坐标和内容
    1. 利用库的内置样式和交互逻辑,减少自定义代码量

通用注意事项

  • 坐标转换:必须使用view.toScreen()将地图坐标转为屏幕坐标,避免Tooltip位置偏移
  • 样式适配:根据项目设计调整Tooltip的背景、阴影、字体等样式,确保和UI风格统一
  • 边界处理:可添加逻辑判断Tooltip是否超出地图容器,超出时自动调整位置(比如左移或上移)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:24:57