首页 > 其他分享 >Taro 自定义地图并接入高德sdk

Taro 自定义地图并接入高德sdk

时间:2023-01-31 15:56:53浏览次数:60  
标签:flex Taro 自定义 pois item let latitude data 高德

小程序项目有用到需要自定义地图的需求,于是记录下操作流程

1、引入高德地图sdk包 下载地址:https://lbs.amap.com/api/wx/download
2、项目中导入并初始化

//导入
import amapFile from '../../../utils/libs/amap-wx.js'  //高德地图sdk
let myAmapFun
//初始化
  componentWillMount = () => {
    /// 初始化高德地图
    myAmapFun = new amapFile.AMapWX({ key: ThirdPartKey.amapKey })
  }

3、获取当前定位 并初始化气泡 并刷新地图底部poi商家显示

  componentDidMount() {
    /// 获取精准定位
    let that = this
    myAmapFun.getRegeo({
      success: (data) => {
        // markersData = data.markers;
        console.log(data)
        var {
          latitude,
          longitude
        } = that.state
        let { pois, addressComponent } = data[0].regeocodeData
        latitude = data[0].latitude
        longitude = data[0].longitude
        let marker
        if (pois.length > 0) {
          marker = this.getMarker(pois[0])
          /// 默认选中第0组数据
          pois[0].checked = true
        }
        /// 加上省市区 让地址变得长一些
        pois.map(item => {
          item.realaddress = addressComponent.province + addressComponent.city + addressComponent.district + item.address
        })
        var markers: any = []
        if (marker) {
          markers.push(marker)
        }
        this.setState({ latitude, longitude, pois, markers })
      },
      fail: (err) => {
        console.log(err)
      }
    })
  }

3、点击搜索进入到键盘输入实时获取周边商家的页面

  onInputValueChange = (e) => {
    const { value } = e.detail
    // console.log(value)
    if (value.length == 0) {

      this.setState({
        searchResults: [],
        // showSearch: false,
        keyword: '',
      }, () => {
        // Taro.hideKeyboard()
      });
      return
    }
    /// 搜索POI功能
    myAmapFun.getInputtips({
      keywords: value,
      // city: '杭州',
      // location: '120.299221,30.419153',
      success: (data) => {
        console.log(data)
        if (data && data.tips) {
          this.setState({
            keyword: value,
            searchResults: data.tips
          });
        }
      }
    })
  }

4、搜索结果点击后重新获取该点击定位的周边的POI并刷新显示

  onResultItemClick = (item) => {
    /// 根据搜索结果 重新定位
    /// 将经纬度字符串转换出来
    try {
      let locations = item.location.split(',')
      let longitude = locations[0]
      let latitude = locations[1]

      let marker = {
        id: item.id,
        latitude,
        longitude,
        name: item.name,
        width: 20,
        height: 30,
      }

      /// 根据经纬度 获取周边的poi
      myAmapFun.getPoiAround({
        location: item.location,
        success: (data) => {
          console.log(data)
          let pois = data.poisData || []
          if (pois.length > 0) {
            pois[0].checked = true
          }
          pois.map(res => {
            res.realaddress = res.pname + res.cityname + res.adname + res.address
          })

          this.setState({
            keyword: '',
            showSearch: false,
            markers: [marker],
            latitude, longitude,
            searchResults: [],
            pois
          })
        },
        fail: (err) => {
          this.setState({
            keyword: '',
            showSearch: false,
            markers: [marker],
            searchResults: [],
            latitude, longitude
          })
        }
      })
    } catch (error) {
      let e = {
        detail: {
          value: item.name,
        }
      }
      this.onInputValueChange(e)
    }
  }

5、点击地图底部POI实时更新气泡角标

  onPoiItemClick = (item: any, index: number) => {
    /// 点击重新设置气泡
    let marker = this.getMarker(item)
    let { pois } = this.state
    /// 清空所有的显示 
    pois.map(data => {
      data.checked = false
      return item
    })
    pois[index].checked = true
    this.setState({
      markers: [marker],
      pois
    })
  }

全部源码
tsx

import React, { Component } from 'react'
import Taro from '@tarojs/taro'
import { ThirdPartKey } from '@/utils/const.js'
import { View, Map, Input, Image } from '@tarojs/components'
import Assets from '@/assets'
import amapFile from '../../../utils/libs/amap-wx.js'  //高德地图sdk
import './index.scss'

let myAmapFun

interface State {
  latitude: number,
  longitude: number,
  markers: any[],
  searchResults: any[],
  pois: any[],
  showSearch: boolean,
  keyword: string,
}

/// 修改和选择已有修理厂
export default class SelectFactoryAddress extends Component<{}, State> {
  state: State = {
    latitude: 23.099994,
    longitude: 113.324520,
    searchResults: [],
    showSearch: false,
    keyword: '',
    pois: [],
    markers: []
  }

  componentWillMount = () => {
    /// 初始化高德地图
    myAmapFun = new amapFile.AMapWX({ key: ThirdPartKey.amapKey })
  }

  componentDidMount() {
    /// 获取精准定位
    let that = this
    myAmapFun.getRegeo({
      success: (data) => {
        // markersData = data.markers;
        console.log(data)
        var {
          latitude,
          longitude
        } = that.state
        let { pois, addressComponent } = data[0].regeocodeData
        latitude = data[0].latitude
        longitude = data[0].longitude
        let marker
        if (pois.length > 0) {
          marker = this.getMarker(pois[0])
          /// 默认选中第0组数据
          pois[0].checked = true
        }
        /// 加上省市区 让地址变得长一些
        pois.map(item => {
          item.realaddress = addressComponent.province + addressComponent.city + addressComponent.district + item.address
        })
        var markers: any = []
        if (marker) {
          markers.push(marker)
        }
        this.setState({ latitude, longitude, pois, markers })
      },
      fail: (err) => {
        console.log(err)
      }
    })
  }

  onInputValueChange = (e) => {
    const { value } = e.detail
    // console.log(value)
    if (value.length == 0) {

      this.setState({
        searchResults: [],
        // showSearch: false,
        keyword: '',
      }, () => {
        // Taro.hideKeyboard()
      });
      return
    }
    /// 搜索POI功能
    myAmapFun.getInputtips({
      keywords: value,
      // city: '杭州',
      // location: '120.299221,30.419153',
      success: (data) => {
        console.log(data)
        if (data && data.tips) {
          this.setState({
            keyword: value,
            searchResults: data.tips
          });
        }
      }
    })
  }

  getMarker = (item: any) => {
    /// 点击重新设置气泡
    let locations = item.location.split(',')
    let longitude = locations[0]
    let latitude = locations[1]

    let marker = {
      id: item.id,
      latitude,
      longitude,
      name: item.name,
      width: 20,
      height: 30,
    }
    return marker
  }

  /// 点击搜索结果
  onResultItemClick = (item) => {
    /// 根据搜索结果 重新定位
    /// 将经纬度字符串转换出来
    try {
      let locations = item.location.split(',')
      let longitude = locations[0]
      let latitude = locations[1]

      let marker = {
        id: item.id,
        latitude,
        longitude,
        name: item.name,
        width: 20,
        height: 30,
      }

      /// 根据经纬度 获取周边的poi
      myAmapFun.getPoiAround({
        location: item.location,
        success: (data) => {
          console.log(data)
          let pois = data.poisData || []
          if (pois.length > 0) {
            pois[0].checked = true
          }
          pois.map(res => {
            res.realaddress = res.pname + res.cityname + res.adname + res.address
          })

          this.setState({
            keyword: '',
            showSearch: false,
            markers: [marker],
            latitude, longitude,
            searchResults: [],
            pois
          })
        },
        fail: (err) => {
          this.setState({
            keyword: '',
            showSearch: false,
            markers: [marker],
            searchResults: [],
            latitude, longitude

          })
        }
      })
    } catch (error) {
      let e = {
        detail: {
          value: item.name,
        }
      }
      this.onInputValueChange(e)
    }
  }

  onPoiItemClick = (item: any, index: number) => {
    /// 点击重新设置气泡
    let marker = this.getMarker(item)
    let { pois } = this.state
    /// 清空所有的显示 
    pois.map(data => {
      data.checked = false
      return item
    })
    pois[index].checked = true
    this.setState({
      markers: [marker],
      pois
    })

    // console.log(item.realaddress)
    // Taro.eventCenter.trigger('selectAddress', {
    //   type: 'factory',
    //   address: item.realaddress,
    // })
    // Taro.navigateBack({})
  }

  cancleSearch = () => {
    this.setState({
      showSearch: false,
      keyword: '',
      searchResults: [],
    })
  }

  onClear = () => {
    this.setState({
      keyword: '',
      searchResults: [],
    })
  }


  render() {  

    let { latitude, longitude, markers, searchResults, showSearch, keyword, pois } = this.state
    return (
      <View className='selectFactoryAddress'>
        <View className='container'>
          {/* 地图 */}
          <View className='map-wrap'>
            <Map
              id="mapId"
              className="map"
              latitude={latitude || 0}
              longitude={longitude}
              showLocation={true}
              markers={markers}
            ></Map>
          </View>
          {/* 搜索 */}
          <View className='search-wrap'>
            <View className='input-wrap'>
              <Input className='input'
                placeholder='请输入关键字搜索'
                value={keyword}
                onInput={this.onInputValueChange.bind(this)}
                onFocus={() => this.setState({ showSearch: true })}
              ></Input>
              {
                keyword.length > 0 && <View className='clear-img' onClick={() => this.onClear()}>
                  <Image className='img' src={Assets('clear.png')} mode='widthFix'></Image>
                </View>
              }
            </View>
            {
              showSearch && <View className='search' onClick={() => this.cancleSearch()}>取消</View>
            }
          </View>

          {/* POI内容 */}
          <View className='poi-wrap' >
            {
              pois.map((item, index) => {
                return (
                  <View className={`poi-item ${item.checked ? 'active' : ''}`} key={index} onClick={() => this.onPoiItemClick(item, index)}>
                    <View className='content'>
                      <View className='name'>{item.name}</View>
                      <View className='address'>{item.realaddress}</View>
                    </View>
                  </View>
                )
              })
            }
          </View>
         {/* 搜索结果页 */}
          {
            showSearch && <View className='search-result-wrap'>
              {
                searchResults.map((item, index) => {
                  return (<View className='result-item' key={index} onClick={() => this.onResultItemClick(item)}>
                    <View className='name'>{item.name}</View>
                    <View className='detail'>{item.district + item.address}</View>
                  </View>)
                })
              }
              {
                searchResults.length == 0 && <View className='nodata-wrap'>
                  <View>暂无数据</View>
                </View>
              }
            </View>
          }
        </View >
      </View >
    )
  }
}

scss

.selectFactoryAddress {
  .container {
    position: relative;
    .search-wrap {
      height: 120px;
      background-color: white;
      position: fixed;
      padding: 0 20px;
      left: 0;
      top: 0;
      right: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      border-top: 1px solid #eee;
      border-bottom: 1px solid #eee;

      .input-wrap {
        width: 90%;
        height: 50%;
        border: 1px solid #eee;
        padding: 0 30px;
        border-radius: 36px;
        display: flex;
        align-items: center;
        .input {
          flex: 1;
          height: 100%;
          font-size: 26px;
          color: #333;
        }
        .clear-img {
          width: 30px;
          height: 30px;
          // background-color: #e63c3d;
          display: flex;
          align-items: center;
          justify-content: center;
          margin-left: 15px;
          .img {
            width: 100%;
            height: 100%;
          }
        }
      }
      .search {
        width: 80px;
        text-align: center;
        color: #3c77df;
        font-size: 28px;
        font-weight: 400;
      }
    }
    .search-result-wrap {
      background-color: white;
      position: absolute;
      left: 0;
      top: 120px;
      right: 0;
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      .result-item {
        // height: 80px;
        border-bottom: 1px solid #eee;
        color: #333;
        font-size: 26px;
        display: flex;
        // align-items: center;
        padding: 10px 20px;
        flex-direction: column;
        .detail {
          font-size: 22px;
          margin-top: 5px;
          color: #999;
        }
      }
      .nodata-wrap {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #999;
        font-size: 30px;
      }
    }
    .map-wrap {
      width: 100vw;
      height: 100vh;
      .map {
        width: 100%;
        height: 100%;
      }
    }
    .item-wrap {
      background-color: white;
      position: fixed;
      left: 0;
      bottom: 0;
      right: 0;
      display: flex;
      flex-direction: column;
      color: #333;
      padding: 20px;
      .sname {
        font-size: 30px;
        font-weight: 500;
      }
      .address-wrap {
        margin-top: 10px;
        font-size: 25px;
        display: flex;

        .address {
          flex: 1;
        }
        .distance {
          min-width: 160px;
          text-align: right;
        }
      }

      .button-wrap {
        margin-top: 10px;
        display: flex;
        background-color: white;
        // border-top: 1px solid #eee;
        height: 100px;
        align-items: center;
        padding: 0 20px;
        .button {
          display: flex;
          justify-content: center;
          align-items: center;
          font-size: 26px;
          color: #333;
          height: 70%;
          border: 1px solid #ddd;
          border-radius: 10px;
        }
        .left {
          width: 50%;
        }
        .right {
          width: 50%;
          margin-left: 20px;
          color: white;
          background-color: #e63c3d;
          border: none;
        }
      }
    }

    .poi-wrap {
      background-color: white;
      position: fixed;
      left: 0;
      bottom: 0;
      right: 0;
      display: flex;
      flex-direction: column;
      color: #333;
      padding: 0 20px;
      max-height: 40%;
      overflow: scroll; //这个属性是重点,要不然内容无法滚动
      .poi-item {
        position: relative;
        padding: 15px;
        display: flex;
        align-items: center;
        font-size: 24px;
        color: #333;
        border-bottom: 1px solid #eee;
        .content {
          flex: 1;
          display: flex;
          flex-direction: column;
          margin-right: 100px;
          .name {
            font-weight: 500;
          }
          .address {
            margin-top: 10px;
            font-size: 20px;
            color: #999;
          }
        }
      }
      .poi-item.active {
        &::after {
          content: "";
          width: 8px;
          height: 20px;
          position: absolute;
          right: 20px;
          top: 30px;
          border: 6px solid red;
          border-top-color: transparent;
          border-left-color: transparent;
          transform: rotate(45deg);
        }
      }
    }
  }
}

标签:flex,Taro,自定义,pois,item,let,latitude,data,高德
From: https://www.cnblogs.com/qqcc1388/p/17079437.html

相关文章

  • mavon-editor自定义添加颜色选择器
    mavon-editor原本是没有带颜色选择器的,产品提出的需求,只好自定义一个了这里是看了源码再加上看别人的博客,然后加了个插槽,我使用的是elementui的颜色选择器el-color-picke......
  • grafana 自定义dashboard Variables
    Variables 示例VariablesDependenciesdashboard显示  ......
  • 微信小程序自定义导航栏机型适配
    自定义微信小程序头部导航栏,有几种方式方式一{"navigationStyle":"custom"//将navigationStyle从默认default改为custom}定义此方法后,头部的导航栏会去掉,导航......
  • vue3实现禁用物理按键返回,但是可以通过自定义app-bar的返回按钮返回
    1.注意app-bar是一个所有页面都会用到的顶部title栏,里面左侧有返回按钮;2.基于1,在app-bar组件的setup里添加这个代码:onMounted(()=>{//不能少history.pu......
  • django 自定义模版过滤器
    虽然DTL给我们内置了许多好用的过滤器。但是有些时候还是不能满足我们的需求。因此Django给我们提供了一个接口,可以让我们自定义过滤器,实现自己的需求。模版过滤器必须要......
  • CAD怎么自定义线型?CAD线型自定义步骤
    有些设计师小伙伴绘制CAD图纸的过程中,在调用CAD线型时,觉得软件中自带的线型不适用,想要自定义CAD线型,那么,CAD怎么自定义线型呢?本节教程小编就来给大家分享一下浩辰CAD软件中......
  • 直播电商平台开发,vue 自定义指令过滤特殊字符
    直播电商平台开发,vue自定义指令过滤特殊字符 /** *@tagsinput只可以輸入数字、字母、汉字 *@examplev-emoji */exportdefault(app)=>{ app.directive('e......
  • SAP UI5 应用如何加载自定义 Theme
    要加载外部自定义主题,开发人员可以通过在页面中静态声明或使用Core.setThemeRoot()方法来设置此主题。这非常类似于对位于不同位置的SAPUI5库使用registerModulePat......
  • Docker 容器添加自定义root ca
    比如如果我们基于了step-ca工具做为我们的ca机制,就会有不可信的问题,业务使用就特别不方便了,以下是一个参考配置实际上很简单就是使用update-ca-certificates更新信息参......
  • js实现自定义网络拓扑图-实战记录
    首先推荐工具库JTopo: jtopo一个好用的交互式HTML5图形库其他的看官方文档            三、基础讲解jtopo的核心对象有Stage、Layer、Canv......