React实现地图找房

业务:使用百度地图API实现地图找房

功能:

  • 展示当前定位城市
  • 展示该城市所有区的房源数据
  • 展示某区下所有镇的房源数据
  • 展示某镇下所有小区的房源数据
  • 展示某小区下的房源数据列表

代码如下:

javascript 复制代码
import React from "react";
import AMapLoader from "@amap/amap-jsapi-loader";
import NavHeader from "../../components/NavHeader/index";

import request from "../../request/index";

import { getCurrenCity } from "../../utils/index";

import "./index.scss";
import axios from "axios";

import { Toast } from "antd-mobile";

export default function Map() {
  // 当前城市的信息
  let map = null;
  let AMap = null;
  let locationId = "";
  let coverList = [];
  let type = "city"; // 市,镇 标记是圆形;区标记是矩形;
  let zoomNumber = 11; // 市 11;镇 13;小区 15
  const [houseList, setHouseList] = React.useState([]);
  const [showFlg, setShowFlg] = React.useState(false);
  const urlBase = "http://localhost:8080";

  React.useEffect(() => {
    loadInit();
  }, []);

  const loadInit = () => {
    // 利用高德地图API,逆地理位置转换 经纬度
    getCurrenCity().then((data) => {
      // console.log("当前地址=》", data);

      locationId = data.value;
      const params = {
        key: "6aae8eb1ea15d5e7ca50af4b079c7687",
        address: `${data.label}`,
      };
      axios
        .get("https://restapi.amap.com/v3/geocode/geo", { params })
        .then((res) => {
          // console.log("地理位置", res);
          const position = res.data.geocodes[0].location.split(",");
          // 初始化地图
          loadMap(position);

          // 获取房源数据
          renderOverlays(locationId);
        });
    });
  };

  const loadMap = (position) => {
    // 加载高德地图API
    AMapLoader.load({
      key: "21c7cb07194d66a059387fb531bd7e43", // 替换为你的高德地图API Key
      version: "2.0",
      plugins: [],
    })
      .then((res) => {
        AMap = res;
        // 初始化地图
        map = new AMap.Map("container", {
          zoom: 11,
          center: position,
        });

        //异步加载控件
        AMap.plugin("AMap.ToolBar", function () {
          const toolbar = new AMap.ToolBar(); //缩放工具条实例化
          map.addControl(toolbar); //添加控件
        });
        AMap.plugin("AMap.Scale", function () {
          const scale = new AMap.Scale(); // 比例尺控件
          map.addControl(scale);
        });

        // 监听地图平移
        map.on("movestart", () => {
          console.log("地图平移开始", showFlg);
          setShowFlg(false);
        });
      })
      .catch((e) => {
        console.error(e);
      });
  };

  // 获取房源数据
  const renderOverlays = (locationId) => {
    try {
      Toast.show({
        icon: "loading",
        content: "加载中...",
        duration: 0,
      });
      request.get("/area/map", { params: { id: locationId } }).then((res) => {
        if (res.body.length > 0) {
          coverList = [];
          // 创建覆盖物
          res.body.forEach((item) => {
            getTypeAndZoom(item);
          });
          // 将 marker 添加到地图
          map.add(coverList);
          Toast.clear();
        }
      });
    } catch (error) {
      alert("获取数据失败");
      Toast.clear();
    }
  };

  // 创建覆盖物
  const getTypeAndZoom = (Object) => {
    const {
      coord: { longitude, latitude },
      value,
      count,
      label,
    } = Object;
    // 点标记显示内容,HTML要素字符串
    const markerContent =
      "" +
      '<div class="custom-content-marker flex_col">' +
      `<span>${label}</span>` +
      `<span>${count}套</span>` +
      "</div>";

    const communityContent =
      "" +
      '<div class="community-content-marker">' +
      `<span>${label}</span>` +
      `<span>${count}套</span>` +
      "</div>";

    const marker = new AMap.Marker({
      position: [longitude, latitude],
      // 将 html 传给 content
      content:
        type === "city" || type === "town" ? markerContent : communityContent,
      offset: new AMap.Pixel(-50, -28),
    });

    marker.id = value;
    marker.typeMarker = type;

    marker.on("click", (e) => {
      const {
        target: { id, typeMarker },
        pixel,
      } = e;
      // console.log("点击了marker", e);

      // 切换typeModel类型
      if (typeMarker === "city") {
        type = "town";
        zoomNumber = 13;
      } else if (typeMarker === "town") {
        type = "area";
        zoomNumber = 15;
      }

      if (typeMarker !== "area") {
        // 清除地图上所有添加的覆盖物
        map.clearMap();

        // 以当前点击的覆盖物为中心放大地图
        map.setZoomAndCenter(zoomNumber, [longitude, latitude]);

        // 传入点击的 id 获取房源
        renderOverlays(id);
      } else {
        renderHouseList(id);

        /* 
        调用地图 panBy() 方法,移动地图到中间为止
        公式:
          垂直位移:(window.innerHeight - 330) / 2 - target.clientY
          水平位移:window.innerWidth / 2 - target.clientX
        */
        const clientX = pixel.getX();
        const clientY = pixel.getY();
        map.panBy(
          window.innerWidth / 2 - clientX,
          (window.innerHeight - 330) / 2 - clientY
        );
      }
    });

    coverList.push(marker);
  };

  // 获取小区的房源数据
  const renderHouseList = (id) => {
    try {
      Toast.show({
        icon: "loading",
        content: "加载中...",
        duration: 0,
      });

      request.get("/houses", { params: { cityId: id } }).then((res) => {
        console.log("小区房源", res);
        if (res.status === 200) {
          const { list } = res.body;
          setHouseList(list);
          setShowFlg(true);
          Toast.clear();
        }
      });
    } catch (error) {
      alert("获取数据失败");
      Toast.clear();
    }
  };

  return (
    <div className="map">
      <NavHeader title="地图找房" />
      {/* 地图容器元素 */}
      <div id="container"></div>
      {/* 小区的房源数据 */}

      <div
        className="house-list"
        style={{ display: showFlg ? "block" : "none" }}
      >
        <div className="header flex flex_r_b ">
          <span className="title">房屋列表</span>
          <span className="more">更多房源</span>
        </div>
        <div
          style={{ overflowY: "auto", overflowX: "hidden", height: "330px" }}
        >
          {houseList.map((item) => (
            <div key={item.houseCode} className=" content flex">
              <img src={urlBase + item.houseImg} alt="" />
              <div className="info flex flex_c_b">
                <div className="span1">{item.title}</div>
                <div className="span2">{item.desc}</div>

                <div className="tag-list flex">
                  {item.tags.map((tag, index) => (
                    <div className="span3" key={index}>
                      {tag}
                    </div>
                  ))}
                </div>

                <div className="span4">
                  {item.price}
                  <span style={{ fontSize: "12px" }}>元/月</span>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

相关视频:https://www.bilibili.com/video/BV1gh411U7JD?spm_id_from=333.788.videopod.episodes\&vd_source=2f48f471bbeafdcd207f29dadcc97a5d\&p=153

gitee地址:https://gitee.com/abcdfdewrw/react_hkzf

高德地图API:https://lbs.amap.com/api/javascript-api-v2/guide/map/map-layer

UI组件库:https://ant-design-mobile.antgroup.com/zh/components/nav-bar

难点:高德地图的使用

相关推荐
阿雄不会写代码25 分钟前
使用java springboot 使用 Redis 作为消息队列
前端·bootstrap·html
m0_7482365843 分钟前
【Nginx 】Nginx 部署前端 vue 项目
前端·vue.js·nginx
@C宝1 小时前
【前端面试题】前端中的两个外边距bug以及什么是BFC
前端·bug
Burt1 小时前
@antfu/eslint 支持 globals 全局变量
前端·uni-app·eslint
m0_528723812 小时前
如何在新窗口打开pdf文件,并修改网页标题
前端·javascript·pdf
m0_748248772 小时前
十七:Spring Boot依赖 (2)-- spring-boot-starter-web 依赖详解
前端·spring boot·后端
请叫我飞哥@2 小时前
HTML5 缩放动画(Zoom In/Out)详解
前端·html5·swift
请叫我飞哥@2 小时前
HTML5 弹跳动画(Bounce Animation)详解
前端·html·html5
qq_458563812 小时前
npm发布自定义包
前端·npm·node.js
Lysun0012 小时前
react构建项目报错 `npm install --no-audit --save @testing-l
javascript·react.js·npm