使用蜂鸟地图完成楼层自定义、房间着色、热力图、添加图片覆盖物、添加dom覆盖物、定位到固定区域的中心点

项目里有用到蜂鸟地图的地方,虽然有跟她们对接,但看他们文档也挺费劲的,要自己慢慢研究好久,有些实在研究不出来让他们帮忙看代码发现一些问题,所以把我发现的需要注意的一些点发上来,希望可以帮助到部分有需要的同学~

在这里插入图片描述
在这里插入图片描述

1.map不能生命周期中,因为添加了dom覆盖物(这个覆盖物比较特殊)之后,想在某个方法中清理掉是找不到这个覆盖物的,所以需要将map放在全局变量中~

let imageMarkers, imageStatusMarkers, mapMarkers, analyser, mask, myMarker, mymap;

const fengniaomap= () => {
	……
}

2.当添加多个图片覆盖物的时候,需要有多个覆盖物变量,虽然覆盖物是全部放到数组里面的,但是也是需要放到不同的覆盖物里面的,这样才可以清除成功,或者重要渲染成功~

 // 添加覆盖物
  const addImgMarker = (data, mapObj) => {
    // if (imageMarkers) {
    //   imageMarkers.forEach((item) => {
    //     item.remove();
    //   });
    //   imageMarkers = null;
    // }

    let url = '/images/marker.png';

    imageMarkers = data.map((feature) => {
      var marker = new fengmap.FMImageMarker({
        url: url,
        x: feature.x,
        y: feature.y,
        anchor: fengmap.FMMarkerAnchor.BOTTOM,
        collision: false,
      });
      var floor = mapObj.getFloor(feature.level);
      marker.addTo(floor);
      return marker;
    });


  };

  // 添加覆盖物
  const addImgStatusMarker = (data, mapObj) => {
    // if (imageStatusMarkers) {
    //   imageStatusMarkers.forEach((item) => {
    //     item.remove();
    //   });
    //   imageStatusMarkers = null;
    // }

    let url = '/images/roomstatus.png';

    imageStatusMarkers = data.map((feature) => {
      var marker = new fengmap.FMImageMarker({
        url: url,
        x: feature.x,
        y: feature.y,
        anchor: fengmap.FMMarkerAnchor.BOTTOM,
        collision: false,
      });
      var floor = mapObj.getFloor(feature.level);
      marker.addTo(floor);
      return marker;
    });
  };


 // 去掉覆盖物
  const remodeMarker = () => {
      if (myMarker) {
        myMarker.remove();
        myMarker = null;
      }
      if (imageMarkers) {
        imageMarkers.forEach((item) => {
          item.remove();
        });
        imageMarkers = null;
      }
      if (imageStatusMarkers) {
        imageStatusMarkers.forEach((item) => {
          item.remove();
        });
        imageStatusMarkers = null;
      }
    }
  };

3.地板着色需要先存储model,然后再进行着色,不然找不到~

   
    // 服务端数据与地图数据绑定
    node?.value?.forEach((item, index) => {
      let res = search(mapObj, { FID: item.fid });

      if (item.status) {
        markerStatusData.push(res[0])
      } else {
        markerData.push(res[0]);
      }

      // 获取诊区坐标
      let coordinates = res[0]?.coordinates[0];
      if (coordinates) {
        // addMapMask(coordinates, index, mapMask, mapObj)
        coordinatesList.push(coordinates);
      }

      // 存储models
      res.forEach((item) => {
        models[item.FID] = item;
      });
      setLastModelData(models);

    });


    //  渲染对应业务数据的model颜色
    node?.value?.forEach((item) => {
      if (item.status) {
        models[item.fid]?.setColor('#D5EDDF', 0.5);
      } else {
        models[item.fid]?.setColor('#E8D29F', 0.5);
      }
    });

	// 如果要渲染热力图,也是使用model着色展示的
         // data?.forEach((item) => {
           // if (item.count >= 0 && item.count <= 10) {
             // models[item.fid]?.setColor('#3D7199', 0.5);
           // } else if (item.count > 10 && item.count <= 20) {
             // models[item.fid]?.setColor('#3685B2', 0.5);
           // } else if (item.count > 20 && item.count <= 30) {
             // models[item.fid]?.setColor('#299BCC', 0.5);
           // } else if (item.count > 30 && item.count <= 40) {
            //  models[item.fid]?.setColor('#17B5E5', 0.5);
          //  } else {
             // models[item.fid]?.setColor('#00D5FF', 0.5);
           // }
         // });

4.点击图片覆盖物的时候,需要出现一个dom窗口展示信息,此窗口为dom覆盖物实现,这里我试过直接给dom覆盖物写onclick方法,不太好使,然后map的所有事件覆盖物都可以用,所以我使用了map事件为图片添加单击事件

        mymap.on('click', (e) => {
          var { targets } = e;
          // console.log('targets=========', targets);
          // 点击除marker外其他地方
          if (myMarker) {
            myMarker.remove();
            myMarker = null;
          }

          let imageClick = false,
            imageTarget,
            floorTarget = [];
          targets.forEach((item) => {
            // 表示点击的image覆盖物,
            if (item.type === 8) {
              imageClick = true;
              imageTarget = item;
            }
          });

          // 如果点击的位置覆盖物,
          if (imageClick) {
            targets.forEach((item) => {
              // 存储地板信息,以便从融合数据中取出相关数据
              if (item.type === 4096) {
                floorTarget.push(item.FID);
              }
            });

            // 查询当前点击元素对应的业务数据
            if (floorTarget && floorTarget.length) {
              roomInfo({
                fids: floorTarget.join(','),
              }).then((res) => {
                if (res?.code === 0 && res?.data) {
                  // 页面只显示一个信息窗marker
                  if (myMarker) {
                    myMarker.remove();
                    myMarker = null;
                  }
                  addPopInfoWindow(imageTarget, res?.data);
                }
              });
            }
          }
        });
        
        //添加FMDomMarker
        const addPopInfoWindow = (marker, data) => {
          var windowHtml;
          var coord = {
            x: 11791544.515983218,
            y: 3418827.0068916455,
          };
          if (marker) {
            coord = {
              x: marker.x,
              y: marker.y,
            };
              windowHtml = `
              <div class="fm-control-popmarker">
                <div class="popcontent">
                  <div class="item">
                    <div class="title">房间</div>
                    <div class="content">${data[0].roomNo}</div>
                  </div>
                  <div class="item">
                    <div class="title">诊位</div>
                    <div class="content">${data[0].roomName}</div>
                  </div>  
                  <div class="item">
                    <div class="title fw500">专业</div>
                    <div class="content fw500">${data[0].majorName}</div>
                  </div> 
                  <div class="item">
                    <div class="title fw500">医生</div>
                    <div class="content fw500">${data[0].doctorName}</div>
                  </div>
                </div>
              </div>
              `;
    
          }
          myMarker = new fengmap.FMDomMarker({
            x: coord.x,
            y: coord.y,
            content: windowHtml,
          });
          var level = mymap.getLevel();
          var floor = mymap.getFloor(level);
          myMarker.addTo(floor);
        };

5.使用的tree树形组件完成的自定义楼层组件,服务端返回每个楼层对应的房间地板id,点击后获取当前id以及相关房间信息,进行展示……

const onCheck = (checkedKeys, e) => {
        if (myMarker) {
            myMarker.remove();
            myMarker = null;
        }
        console.log('checkedKeys, info', checkedKeys, e);
        setselectkey();
        setselectkey(checkedKeys);
        setselectInfo(e.node)
        setDataSource([]);

        // setSelectInfo(info);

        //  设置聚焦楼层
        let level = e.node.level;
        if (!level) {
            return;
        }
        mymap.setLevel({
            level: Number(e.node.level),
            finish: () => {
                toggleLayer(mymap, 'LABLE');
                toggleLayer(mymap, 'FACILITY');

                // 只有诊室才跳转
                if (e.node.flag === 2) {
                    handleCenterShow(mymap, e.node);
                }
            },
        });
    };

6.定位到区域中心点,区域是由多个房间组成的,把所有房间的中心点相加再除以数量,就可以计算出整体的中心点了

// 点击定位到中心点
const handleCenter = (mapObj, fidlists) => {
    if (!fidlists) {
        return;
    }
    let boundList = [];
    fidlists.forEach((fid) => {
        let searchRes = search(mapObj, { FID: fid });
        searchRes?.forEach((ele) => {
            boundList.push([ele.x, ele.y]);
        });
    });
    const center = findCenter(boundList);
    // mapObj.setCenter({ x: 12857436.062710293, y: 4710362.9075});
    mapObj.setCenter({ x: center.x, y: center.y });
};

// 获得中心坐标
const findCenter = (markers) => {
    let x = 0;
    let y = 0;

    for (let i = 0; i < markers.length; ++i) {
        x += markers[i][0];
        y += markers[i][1];
    }

    x /= markers.length;
    y /= markers.length;

    return { x: x, y: y };
};

然后其他的就是一些基本的配置了~ 代码我全部放在这里,大家有问题评论区给我留言吧~

import { useEffect, useState } from 'react';

import 'fengmap/build/fengmap.analyser.min'; //分析器
import fengmap from 'fengmap/build/fengmap.map.min'; //核心包
import { transData } from '@/assets/js/tool.js';

import Icon from '@/components/DTIIcon/DTIIcon';

import { areaTree, roomInfo } from '@/api/project';


let imageMarkers, imageStatusMarkers, mapMarkers, analyser, mask, myMarker, mymap;

const DiagnosisSpace = () => {
    const [activeTab, setActiveTab] = useState(tabOptions[0].id); // 当前选中tab
    const [activeDate, setActiveDate] = useState(dateTabOptions[0].id); // 当前选中tab

    const [selectkey, setselectkey] = useState([]); // 树高亮
    const [expandedKeys, setExpandedKeys] = useState([]);
    const [autoExpandParent, setAutoExpandParent] = useState(true);
    const [treeData, setTreeData] = useState([]);
    const [availableRooms, setAvailableRooms] = useState([]);
    const [columns, setColumns] = useState([]);
    const [dataSource, setDataSource] = useState([]);
    const [lastLevelData, setLastLevelData] = useState([]);
    const [lastModelData, setLastModelData] = useState([]);
    const [featureTab, setFeatureTab] = useState(false);
    const [selectInfo, setselectInfo] = useState({})

    let maskOptions = {
        // 拉伸高度,默认为+∞,表示掩膜垂直方向上的厚度;
        extrudeHeight: 100,
        // 离地高度, 默认为-∞,表示掩膜垂直方向上距离地面的起始高度
        height: -2,
        // 需要参与掩膜的Layer,如[fengmap.FMType.MODEL_LAYER, fengmap.FMType.FACILITY_LAYER, fengmap.FMType.LABEL_LAYER, fengmap.FMType.EXTERNAL_MODEL_LAYER, fengmap.FMType.EXTENT_LAYER]
        types: [
            fengmap.FMType.MODEL_LAYER,
            fengmap.FMType.FACILITY_LAYER,
            fengmap.FMType.LABEL_LAYER,
            fengmap.FMType.EXTERNAL_MODEL_LAYER,
            // fengmap.FMType.EXTENT_LAYER,
        ],
        //掩膜区域内部还是外部,取值'inside'或'outside',默认为'inside'
        showRegion: 'inside',
    };


    function findNodeByValue(tree, title) {
        for (let node of tree) {
            if (node.title === title) {
                return [node]
            }
            if (node.children) {
                const result = findNodeByValue(node.children, title)
                if (result) {
                    return [node, ...result]
                }
            }
        }
        return null
    }



    useEffect(() => {
        // 楼层层级信息
        let level = 1,
            defaultInfo;

        // 左侧楼层切换
        areaTree().then((res) => {
            if (res?.code === 0 && res?.data) {
                let data = _.cloneDeep(transData(res?.data, 'key', 'pid', 'children'));

                setTreeData(data);
                const result = findNodeByValue(data, '内科专科')
                defaultInfo = result[2];
                setExpandedKeys([result[0].key, result[1].key]);
                // defaultInfo = data[0].children[0].children[0];
                // setExpandedKeys([data[0].key, data[0].children[0].key]);
                level = Number(defaultInfo.level);
                setselectkey([defaultInfo.key]);
                setselectInfo(defaultInfo)


                const mapOptions = {
                    appName: 'daozhen',
                    key: 'dcefb32e9830e6148e9b6554ec25d8ab',
                    mapID: '1749352967085703169',
                    container: document.getElementById('fengmap'),
                    // mapURL与themeURL不可以编译打包,需存放在静态文件夹下
                    mapURL: '/data/',
                    themeURL: '/data/theme/',
                    themeID: '1750086376946995201',
                    // visibleLevels: [1, 2],
                    // level: 1,
                    backgroundColor: '#FFFFFF',
                    // 高精度模型时添加此属性,但目前有些问题
                    // externalModelURL:'./data/theme/1750086376946995201',
                    // 使用案例数据时添加此属性让地图正常显示
                    mapZoom: 21,
                    zoomRange: [10, 25],
                    // highlightColor: []
                    // rotation:50,
                    // tiltAngle: 60,
                    // maxTiltAngle:70,
                    // minTiltAngle:40
                };

                mymap = new fengmap.FMMap(mapOptions);


                // console.log('fengmap.FMType', fengmap.FMType);
                // label显示ename字段
                // console.log('label显示ename字段', fengmap.FMLabelField.ENAME);
                // label显示FID字段
                // console.log('label显示FID字段', fengmap.FMLabelField.FID);
                // FMModel 模型对象显示FID字段
                // console.log('FMModel 模型对象显示FID字段', mymap.FID);

                // 对地图的拖拽、缩放、旋转等操作控制
                let interacation = mymap.getInteractions();
                interacation.enableDrag = false;
                interacation.enableRotate = false;
                interacation.enableTilt = false;
                interacation.enableZoom = false;

                //过滤不允许点击的地图元素,设置为true为允许点击,设置为false为不允许点击
                mymap.pickFilterFunction = function (event) {
                    return (
                        event.type == fengmap.FMType.IMAGE_MARKER || event.type == fengmap.FMType.MODEL
                        // || event.type === fengmap.FMType.EXTERNAL_MODEL
                    );
                };

                // 获取地图对应的key
                const getKeyByValue = (obj, value) => {
                    const result = Object.entries(obj).find(([key, val]) => val === value);
                    return result ? result[0] : null;
                };

                /* 鼠标悬停事件监听 */
                mymap.on('hover', function (event) {
                    // updateUI(event);
                });
                /* 更新拾取信息 */
                const updateUI = (event) => {
                    // 拾取模型对象
                    let target = event.targets[0];
                    // 拾取模型类型
                    let mType = getKeyByValue(fengmap.FMType, target?.type) || 'NONE';
                    // 封装拾取信息
                    let infoHtml = '<div class="layui-card-body">';
                    infoHtml += `<p><label>事件触发:</label>${event.type}</p>`;
                    infoHtml += `<p><label>悬停对象类:</label>${mType}</p>`;
                    infoHtml += `<p><label>level:</label>${event?.level || ''}</p>`;
                    infoHtml += `<p><label>FID:</label>${target?.FID || ''}</p>`;
                    infoHtml += `<p><label>type:</label>${target?.type || ''}</p>`;

                    infoHtml += `<p><label>元素中心点坐标:</label>x:${target?.x || ''}<br/>y:${target?.y || ''
                        }</p>`;
                    infoHtml += `</div>`;
                    let infoDiv = document.getElementById('info');
                    infoDiv.innerHTML = infoHtml;
                };

                // 地图加载完成事件
                mymap.on('loaded', function (e) {
                    initAnalyser(() => {
                        //  设置聚焦楼层
                        if (level) {
                            mymap.setLevel({
                                level: level,
                                finish: () => {
                                    toggleLayer(mymap, 'LABLE');
                                    toggleLayer(mymap, 'FACILITY');

                                    // 只有诊室才跳转
                                    if (activeTab === 'today') {
                                        handleCenterShow(mymap, defaultInfo);
                                    } else {
                                        getAreaCount(defaultInfo.key, activeDate);
                                    }
                                },
                            });
                        }
                    });
                });

                mymap.on('click', (e) => {
                    var { targets } = e;
                    // console.log('targets=========', targets);
                    // 点击除marker外其他地方
                    if (myMarker) {
                        myMarker.remove();
                        myMarker = null;
                    }

                    let imageClick = false,
                        imageTarget,
                        floorTarget = [];
                    targets.forEach((item) => {
                        // 表示点击的image覆盖物,
                        if (item.type === 8) {
                            imageClick = true;
                            imageTarget = item;
                        }
                    });

                    // 如果点击的位置覆盖物
                    if (imageClick) {
                        targets.forEach((item) => {
                            // 存储地板信息,以便从融合数据中取出相关数据
                            if (item.type === 4096) {
                                floorTarget.push(item.FID);
                            }
                        });

                        // 查询当前点击元素对应的业务数据
                        if (floorTarget && floorTarget.length) {
                            roomInfo({
                                fids: floorTarget.join(','),
                            }).then((res) => {
                                if (res?.code === 0 && res?.data) {
                                    // 页面只显示一个信息窗marker
                                    if (myMarker) {
                                        myMarker.remove();
                                        myMarker = null;
                                    }
                                    addPopInfoWindow(imageTarget, res?.data);
                                }
                            });
                        }
                    }
                });

                //添加FMDomMarker
                const addPopInfoWindow = (marker, data) => {
                    var windowHtml;
                    var coord = {
                        x: 11791544.515983218,
                        y: 3418827.0068916455,
                    };
                    if (marker) {
                        coord = {
                            x: marker.x,
                            y: marker.y,
                        };
                        windowHtml = `
              <div class="fm-control-popmarker">
                <div class="popcontent">
                  <div class="item">
                    <div class="title">房间</div>
                    <div class="content">${data[0].roomNo}</div>
                  </div>
                  <div class="item">
                    <div class="title">诊位</div>
                    <div class="content">${data[0].roomName}</div>
                  </div>  
                  <div class="item">
                    <div class="title fw500">专业</div>
                    <div class="content fw500">${data[0].majorName}</div>
                  </div> 
                  <div class="item">
                    <div class="title fw500">医生</div>
                    <div class="content fw500">${data[0].doctorName}</div>
                  </div>
                </div>
              </div>
              `;

                    }
                    myMarker = new fengmap.FMDomMarker({
                        x: coord.x,
                        y: coord.y,
                        content: windowHtml,
                    });
                    var level = mymap.getLevel();
                    var floor = mymap.getFloor(level);
                    myMarker.addTo(floor);
                };

                // 初始化分析器,所有初始化事件都要放在这里才可以执行
                const initAnalyser = (callback) => {
                    analyser = new fengmap.FMSearchAnalyser(
                        {
                            map: mymap,
                        },
                        () => {
                            callback && callback();
                        },
                    );
                };
            }
        });
    }, []);

    // 节点展开
    const onExpand = (newExpandedKeys) => {
        setExpandedKeys(newExpandedKeys);
        setAutoExpandParent(false);
    };

    // 自定义左侧tree节点展示
    const treeTitleRender = (nodeData) => {
        return (
            <div
                className={classnames('treeitem', {
                    'treeitem-disabled': nodeData.disabled,
                })}
            >
                <span className="tree_item_title">{nodeData.title}</span>
            </div>
        );
    };

    // 自定义Tree展开收起Icon
    const switcherIconRender = ({ expanded }) => {
        if (expanded) {
            return <Icon className="expend-icon" type="icon-shuzi-tiaomushouqi" />;
        } else {
            return <Icon className="expend-icon" type="icon-shuzi-tiaomuzhankai" />;
        }
    };

    // 图层控制
    const getLayerByType = (floor, layerType) => {
        var layers = floor.getLayers();
        for (var index = 0; index < layers.length; index++) {
            const layer = layers[index];
            if (layer.type === layerType) {
                return layer;
            }
        }
    };

    const toggleLayer = (mapObj, layerName) => {
        let layer;
        mapObj.getVisibleLevels().forEach((level) => {
            let floor = mapObj.getFloor(level);

            if (layerName === 'LABLE') {
                layer = getLayerByType(floor, fengmap.FMType.LABEL_LAYER);
            }
            if (layerName === 'EXTENT') {
                layer = getLayerByType(floor, fengmap.FMType.EXTENT_LAYER);
            }
            if (layerName === 'MODEL') {
                layer = getLayerByType(floor, fengmap.FMType.MODEL_LAYER);
            }
            if (layerName === 'FACILITY') {
                layer = getLayerByType(floor, fengmap.FMType.FACILITY_LAYER);
            }
            if (layerName === 'EXTERNALMODEL') {
                layer = getLayerByType(floor, fengmap.FMType.EXTERNAL_MODEL_LAYER);
            }
            layer.visible = false;
        });
    };

    // 点击左侧楼层控件事件
    const onCheck = (checkedKeys, e) => {
        if (myMarker) {
            myMarker.remove();
            myMarker = null;
        }
        console.log('checkedKeys, info', checkedKeys, e);
        setselectkey();
        setselectkey(checkedKeys);
        setselectInfo(e.node)
        setDataSource([]);

        // setSelectInfo(info);

        //  设置聚焦楼层
        let level = e.node.level;
        if (!level) {
            return;
        }
        mymap.setLevel({
            level: Number(e.node.level),
            finish: () => {
                toggleLayer(mymap, 'LABLE');
                toggleLayer(mymap, 'FACILITY');

                // 只有诊室才跳转
                if (e.node.flag === 2) {
                    handleCenterShow(mymap, e.node);
                }
            },
        });
    };

    // 构建查询器
    const search = (mapObj, params) => {
        let analyser = new fengmap.FMSearchAnalyser({
            map: mapObj,
        });
        //创建查询实体对象
        let searchRequest = new fengmap.FMSearchRequest();
        //配置levels参数
        if (params.levels) {
            searchRequest.levels = params.levels;
        }
        if (params.level) {
            searchRequest.levels = [params.level];
        }
        if (params.FID) {
            searchRequest.addCondition({ FID: params.FID });
        }
        //配置nodeType参数
        searchRequest.type = params.nodeType ? params.nodeType : fengmap.FMType.MODEL;
        //获取搜索结果
        let sortRes = [];
        analyser.query(searchRequest, (result) => {
            sortRes = mapObj?.getNodes(result); //获取地图对象
        });
        return sortRes;
    };

    const handleCenterShow = (mapObj, node) => {
        // 定义存放颜色更改的fid集合
        let models = {};
        let markerData = [], markerStatusData = [],
            coordinatesList = [];


        if (node?.value?.length) {
            setLastLevelData(node?.value);
        } else {
            models = lastModelData;
            lastLevelData.forEach((item) => {
                if (item.status) {
                    models[item.fid]?.setColor('#D5EDDF', 0.5);
                } else {
                    models[item.fid]?.setColor('E8D29F', 0.5);
                }
            });
        }

        // 把地图定位到中心坐标点
        if (node?.value.length) {
            let fids = node?.value?.map((item) => item.fid);
            handleCenter(mapObj, fids);
        }

        // 服务端数据与地图数据绑定
        node?.value?.forEach((item, index) => {
            let res = search(mapObj, { FID: item.fid });

            if (item.status) {
                markerStatusData.push(res[0])
            } else {
                markerData.push(res[0]);
            }

            // 获取诊区坐标
            let coordinates = res[0]?.coordinates[0];
            if (coordinates) {
                // addMapMask(coordinates, index, mapMask, mapObj)
                coordinatesList.push(coordinates);
            }

            // 存储models
            res.forEach((item) => {
                models[item.FID] = item;
            });
            setLastModelData(models);

        });


        //  渲染对应业务数据的model颜色
        node?.value?.forEach((item) => {
            if (item.status) {
                models[item.fid]?.setColor('#D5EDDF', 0.5);
            } else {
                models[item.fid]?.setColor('#E8D29F', 0.5);
            }
        });

        // 不可用状态,添加覆盖物
        addImgMarker(markerData, mapObj);
        // 可用状态-添加覆盖物
        addImgStatusMarker(markerStatusData, mapObj);

        // addMapMask(coordinatesList, mapObj)

    };

    // 添加覆盖物
    const addImgMarker = (data, mapObj) => {
        // if (imageMarkers) {
        //   imageMarkers.forEach((item) => {
        //     item.remove();
        //   });
        //   imageMarkers = null;
        // }

        let url = '/images/marker.png';

        imageMarkers = data.map((feature) => {
            var marker = new fengmap.FMImageMarker({
                url: url,
                x: feature.x,
                y: feature.y,
                anchor: fengmap.FMMarkerAnchor.BOTTOM,
                collision: false,
            });
            var floor = mapObj.getFloor(feature.level);
            marker.addTo(floor);
            return marker;
        });


    };

    // 添加覆盖物
    const addImgStatusMarker = (data, mapObj) => {
        // if (imageStatusMarkers) {
        //   imageStatusMarkers.forEach((item) => {
        //     item.remove();
        //   });
        //   imageStatusMarkers = null;
        // }

        let url = '/images/roomstatus.png';

        imageStatusMarkers = data.map((feature) => {
            var marker = new fengmap.FMImageMarker({
                url: url,
                x: feature.x,
                y: feature.y,
                anchor: fengmap.FMMarkerAnchor.BOTTOM,
                collision: false,
            });
            var floor = mapObj.getFloor(feature.level);
            marker.addTo(floor);
            return marker;
        });
    };

    //添加区域掩膜
    const addMapMask = (data, mapObj) => {
        if (mapMarkers) {
            mapMarkers.forEach((item) => {
                item.remove();
            });
            mapMarkers = null;
        }
        if (mapObj) {
            mapMarkers = data.map((points) => {
                var mask = new fengmap.FMMapMask({
                    // 坐标点数组
                    points: points,
                    ...maskOptions,
                });
                var floor = mapObj.getFloor(mapObj.getLevel());
                mask.addTo(floor);
                return mask;
            });
        }
    };

    // 去掉覆盖物
    const remodeMarker = () => {
        if (myMarker) {
            myMarker.remove();
            myMarker = null;
        }
        if (imageMarkers) {
            imageMarkers.forEach((item) => {
                item.remove();
            });
            imageMarkers = null;
        }
        if (imageStatusMarkers) {
            imageStatusMarkers.forEach((item) => {
                item.remove();
            });
            imageStatusMarkers = null;
        }
    }
};


// 点击定位到中心点
const handleCenter = (mapObj, fidlists) => {
    if (!fidlists) {
        return;
    }
    let boundList = [];
    fidlists.forEach((fid) => {
        let searchRes = search(mapObj, { FID: fid });
        searchRes?.forEach((ele) => {
            boundList.push([ele.x, ele.y]);
        });
    });
    const center = findCenter(boundList);
    // mapObj.setCenter({ x: 12857436.062710293, y: 4710362.9075});
    mapObj.setCenter({ x: center.x, y: center.y });
};

// 获得中心坐标
const findCenter = (markers) => {
    let x = 0;
    let y = 0;

    for (let i = 0; i < markers.length; ++i) {
        x += markers[i][0];
        y += markers[i][1];
    }

    x /= markers.length;
    y /= markers.length;

    return { x: x, y: y };
};

return (
    <div className={styles.container}>
        <div className="treelist" id="treelist">
            {treeData.length > 0 && (
                <Tree
                    onExpand={onExpand}
                    expandedKeys={expandedKeys}
                    autoExpandParent={autoExpandParent}
                    treeData={treeData}
                    titleRender={treeTitleRender}
                    selectedKeys={selectkey}
                    onSelect={onCheck}
                    switcherIcon={switcherIconRender}
                    defaultExpandAll={true}
                    showLine={false}
                />
            )}
        </div>
        <div
            className={classnames('fengmap', { map: activeTab === 'fueature' })}
            id="fengmap"
        ></div>
    </div>
);
};

export default DiagnosisSpace;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/466457.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣Lc17--- 345.反转字符串中的元音字母(java版)-2024年3月18日

1.题目 2.知识点 注1&#xff1a; indexOf() 是 Java 中 String 类的方法之一&#xff0c;它用于查找指定字符或字符串在字符串中第一次出现的位置。如果找到了该字符或字符串&#xff0c;则返回它在字符串中的索引位置&#xff08;从0开始&#xff09;&#xff0c;如果没有找…

读《Cheating Depth: Enhancing 3D Surface Anomaly Detection via Depth Simulation》

WCAV2024 摘要&引言 RGB骨干&#xff1a;某些表面异常仅在RGB中实际上仍然是看不见的&#xff0c;因此需要合并三维信息&#xff08;确实重点在于“合并”&#xff0c;单纯看例子里的深度图片也看不出来异常在哪里&#xff0c;但是和rgb overlay之后就明显一些了&#xf…

2024年pmp的考试时间是什么时候?

2024年 PMP 考试时间已经定了 &#xff0c;分别是 3 月、6月、8月、11月 &#xff0c;4月就准备报6月的考试了&#xff0c;有想法的别错过啦~ 一、报考条件 报考条件其实挺简单的&#xff0c;最核心的条件还是满足以下 2 个&#xff1a;1、本科毕业需要满 3 年时间&#xff0c…

网络编程--高并发服务器

这里写目录标题 引入场景 多进程并发服务器二级目录二级目录二级目录 多线程并发服务器二级目录二级目录二级目录 多路IO转接服务器设计思路对比引入 select函数简介参数介绍第一个参数第234参数返回值对于第234参数的应用对于最后一个参数总结 附加操作&#xff08;附加四个函…

项目试运行报告-word

一、试运行目的 软件项目试运行的主要目的是在实际应用环境中对软件系统进行全面检验&#xff0c;确保其满足设计要求和用户需求&#xff0c;同时发现和解决潜在的问题&#xff0c;为正式投入使用做好准备。通过试运行&#xff0c;我们可以&#xff1a; 验证软件系统的稳定性…

国创证券|资源再生概念持续活跃,超越科技两连板,大地海洋等走高

资源再生概念15日盘中再度走强&#xff0c;截至发稿&#xff0c;超越科技涨停斩获两连板&#xff0c;深水海纳涨超14%&#xff0c;大地海洋涨超12%&#xff0c;华新环保涨近9%&#xff0c;天奇股份、格林美、怡球资源等涨超5%。 消息面上&#xff0c;3月13日&#xff0c;国务院…

全新2024快递平台系统 独立版快递信息查询小程序源码 cps推广营销流量主+前端 同城快递平台

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 快递代发快递代寄寄件小程序可以对接易达云洋一级总代 快递小程序&#xff0c;接入云洋/易达物流接口&#xff0c;支持选择快递公司&#xff0c;三通一达&#xff0c;极兔&#xff0c…

Python the code is unreachable

Python the code is unreachable 正文 正文 相信有不少小伙伴在使用 Python 的时候有时候会遇到 the code is unreachable 这样的 warning 提示。这种提示表示在我们当前书写的代码种有一部分代码被屏蔽了。可能会存在潜在的 bug&#xff0c;需要我们注意&#xff0c;那么什么…

Three 光源 (总结四)

萤火虫飞舞 import * as THREE from three import { OrbitControls } from ../../js/jsm/controls/OrbitControls.js; // 引入相机控件let scene, camera, renderer, controls, flyBall, ball function init() {scene new THREE.Scene()camera new THREE.PerspectiveCamera(7…

幸福金龄会第二届《锦绣中华》中老年文旅文化艺术节圆满落幕

广东&#xff0c;这片承载着深厚文化底蕴的土地&#xff0c;再次见证了中老年文化艺术的璀璨盛放。近日&#xff0c;由幸福金龄会主办、广之旅协办的第二届《锦绣中华》中老年文旅文化艺术节在广东隆重举行。活动汇聚了广东各支文艺团队&#xff0c;他们用最真挚的表演&#xf…

讲述微信小程序 通信模型

之前的文章 讲述微信小程序宿主环境 我们讲到了 手机微信 为小程序 提供了多方面支持 包括 1 通讯模型 2 运行机制 3 组件 4 API 今天 我们就来说 通讯模型 小程序中的 通信主题 是 渲染层 和 逻辑层 首先 渲染层中 包含的是 wxml 页面模板 和 wxss样式 逻辑层 里面则都是js的…

如何从视频中提取gif?仅需三步在线制作

视频提取GIF是一种常见的图像处理技术&#xff0c;它可以将视频中的某一段或某一帧提取出来&#xff0c;并保存为GIF格式的动图。这种技术在互联网上广泛应用&#xff0c;成为了分享精彩瞬间和制作有趣动画的有力工具。想要从视频中截取动图&#xff0c;使用视频转gif工具&…

超越标签的探索:K-means与DBSCAN在数据分析中的新视角

最近在苦恼为我的数据决定分组问题&#xff0c;在查找资料时&#xff0c;恰好看到机器学习中的无监督学习的聚类分析&#xff0c;正好适用于我的问题&#xff0c;但是我之前学机器学习时。正好没有学习无监督部分&#xff0c;因为我认为绝大多数问题都是有标签的监督学习&#…

IPSEC VPN-详解原理

目录 IPSEC提供的安全服务 IPSEC协议簇 ​编辑 安全协议 1.传输模式 2. 隧道模式 AH ---鉴别头协议 AH提供的安全服务&#xff1a; AH头部 AH的保护范围 1.传输模式 2.隧道模式 ​编辑 ESP ---封装安全载荷协议 ESP提供的安全服务&#xff1a; ESP的头部 ESP的保护范围 1.传输…

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程

在讲进程之前首先就是需要去回顾一下我们之前学的操作系统是干嘛的&#xff0c;首先操作系统是一个软件&#xff0c;它是对上提供一个良好高效&#xff0c;稳定的环境的&#xff0c;这是相对于用户来说的&#xff0c;对下是为了进行更好的软硬件管理的&#xff0c;所以操作系统…

es文档操作命令

文档操作 documents 创建数据&#xff08;put&#xff09; 向 user 索引下创建3条数据 PUT /user/_doc/1 {"name":"zhangsan","age":18,"sex":"男","info":"一顿操作猛如虎&#xff0c;一看工资2500"…

关于卷积神经网络特征可视化

卷积神经网络CNN&#xff0c;一个大号/深层的&#xff0c;现代的&#xff0c;黑箱的&#xff0c;信号/图像处理器。 简单讲解如何将图像输入到卷积神经网络CNN并显示网络不同层的激活图&#xff0c;并通过将激活图与原始图像进行比较以探索网络学习哪些特征 本例来源于Mathwo…

IP代理技术革新:探索数据采集的新路径

引言&#xff1a; 随着全球化进程不断加深&#xff0c;网络数据采集在企业决策和市场分析中扮演着愈发重要的角色。然而&#xff0c;地域限制和IP封锁等问题常常给数据采集工作带来了巨大挑战。亿牛云代理服务凭借其强大的网络覆盖和真实住宅IP资源&#xff0c;成为解决这些问…

大A为何频繁跳水,Python量化1200W条交易数据给你答案!| 邢不行

这是邢不行第 110 期量化小讲堂的分享 作者 | 邢不行、密斯锌硒 常看我文章的读者应该能发现&#xff0c;我介绍过的量化策略大多都会在开盘时买入。 比如小市值策略和散户反着买策略&#xff1a; 小市值策略文章 散户反着买策略 它们都会在每个周期的第一个交易日开盘去…

Git Bash命令初始化本地仓库,提交到远程仓库

git init&#xff1a;初始化空仓库 // 初始化一个空仓库或者重新初始化一个存在的仓库 git init git remote // 为当前本地仓库添加一个远程仓库地址 git remote add origin https://gitee.com/xxx/demo.git git pull // 从设置好链接的远程仓库拉去已经存在的数据&#xff0c;…