vue3.0 + Tencent マップ + ドラッグ選択 + キーワード検索 (「Worker」で「postMessage」の実行に失敗しました: [オブジェクト オブジェクト] を cl にすることができませんでした)

1. 初期段階

1. Tencent Maps の公式 Web サイト、コンソール - アプリケーション管理 - アプリケーションの作成からキー値を取得します。

 

 2. アプリケーションが正常に作成されたら、キーの値を設定します。

2、機能

1.Tencent Mapsのjsを導入し、 vueのパブリックフォルダのindex.htmlに以下の記述を追加します。

 <script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=在官网控制台获取的key"></script>

 2. マップ コンポーネント Map.vue を作成します - マップを初期化します

 <div id="map" />

   地図と中心点の初期化、地図のドラッグの監視

 注:  reactive, refにmapmarKerLayer を書き込まないでください、後で中心点を変更するときにエラーが報告されます。

       

       「Worker」で「postMessage」を実行できませんでした: [オブジェクト オブジェクト] を複製できませんでした

 var map = null // 地图
 var markerLayer = null// 点标记
// 初始化地图/定位
    const getinitChange = (lat, lng) => {
      console.log(lat, lng)
      // 定义地图中心点坐标
      const myLatlng = new window.TMap.LatLng(lat, lng)
      vueConfig.lat = lat
      vueConfig.lng = lng
      // 定义map变量,调用 window.TMap.Map() 构造函数创建地图
      map = new window.TMap.Map(document.getElementById('map'), {
        center: myLatlng, // 设置地图中心点坐标
        zoom: 17.2 // 设置地图缩放级别
      })
      var geometries = {
        id: '1', // 点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
        styleId: 'myStyle', // 指定样式id
        position: myLatlng // 点标记坐标位置
      }
      markerLayer = new window.TMap.MultiMarker({
        map: map,
        styles: {
          // 创建一个styleId为"myStyle"的样式(styles的子属性名即为styleId)
          myStyle: new window.TMap.MarkerStyle({
            width: 25, // 点标记样式宽度(像素)
            height: 30 // 点标记样式高度(像素)
          })
        },
        // 点标记数据数组
        geometries: [geometries]
      })
      // 监听地图正在平移的状态
      map.on('pan', function() {
        markerLayer.updateGeometries([
          {
            'styleId': 'myStyle',
            'id': '1',
            'position': map.getCenter()
          }
        ])
      })
      // 监听地图结束平移
      map.on('panend', function() { // 拖拽结束时获取地址
        getInverseAnalysis()
      })
    }

3. キーワード検索

<el-autocomplete
        v-model="vueConfig.address"
        value-key="title"
        :fetch-suggestions="querySearch"
        :trigger-on-focus="false"
        @select="handleSelect"
      >
        <template #append>
          <el-button icon="el-icon-search" />
        </template>
</el-autocomplete>
 // 关键字查询
    const querySearch = (queryString, callback) => {
      const url = 'https://apis.map.qq.com/ws/place/v1/suggestion' // 关键字查询
      jsonp(url, {
        key: vueConfig.key,
        keyword: queryString,
        output: 'jsonp'
      })
        .then(res => {
          if (res.status == 0) {
            const list = res.data
            callback(list)
          } else {
            ElMessage({
              type: 'error',
              message: res.message
            })
          }
        })
    }

 // 选择地址
    const handleSelect = (item) => {
      vueConfig.lat = item.location.lat
      vueConfig.lng = item.location.lng
      vueConfig.location = item
      vueConfig.ispan = false
      setInitChange()
    }

4. 地図の位置を変更する

// 修改地图位置
    const setInitChange = () => {
      map.setCenter(new window.TMap.LatLng(vueConfig.lat, vueConfig.lng))
      markerLayer.updateGeometries([
        {
          'styleId': 'myStyle',
          'id': '1',
          'position': new window.TMap.LatLng(vueConfig.lat, vueConfig.lng)
        }
      ])
    }

5. 現在位置を取得して地図を初期化する

 // 获取当前位置
    const getNowLngAndLat = () => {
      const url = 'https://apis.map.qq.com/ws/location/v1/ip'
      jsonp(url, {
        key: vueConfig.key,
        output: 'jsonp'
      })
        .then(res => {
          if (res.status == 0) {
            vueConfig.lat = res.result.location.lat
            vueConfig.lng = res.result.location.lng
            getinitChange(vueConfig.lat, vueConfig.lng)
          } else {
            ElMessage({
              type: 'error',
              message: res.message
            })
          }
        })
    }

6. アドレスの逆解析

 // 逆解析地址
    const getInverseAnalysis = () => {
      const location = `${map.getCenter().lat},${map.getCenter().lng}`
      const url = 'https://apis.map.qq.com/ws/geocoder/v1/?location='
      jsonp(url, {
        location: location,
        output: 'jsonp',
        key: vueConfig.key
      })
        .then(res => {
          if (res.status == 0) {
            if (vueConfig.ispan) {
              vueConfig.lat = res.result.location.lat
              vueConfig.address = res.result.formatted_addresses.recommend
              vueConfig.lng = res.result.location.lng
            }
            vueConfig.ispan = true
          } else {
            ElMessage({
              type: 'error',
              message: res.message
            })
          }
        })
        .catch(err => {
          console.log(err)
        })
    }

3. 完全なコード

<template>
  <el-dialog
    v-model="vueConfig.dialogAddressVisible"
    title="获取经纬度"
    :close-on-click-modal="false"
    :destroy-on-close="true"
    :append-to-body="true"
    width="55%"
    @close="handleClose()"
  >
    <div class="map-input">
      <el-autocomplete
        v-model="vueConfig.address"
        value-key="title"
        :fetch-suggestions="querySearch"
        :trigger-on-focus="false"
        @select="handleSelect"
      >
        <template #append>
          <el-button icon="el-icon-search" />
        </template>
      </el-autocomplete>

    </div>
    <div id="map" />
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="handleClose()">取消</el-button>
        <el-button type="primary" @click="confirmMap">确认地址</el-button>
      </span>
    </template>
  </el-dialog>
</template>
<script >
import { reactive, nextTick, watch } from 'vue'
import { jsonp } from 'vue-jsonp'
import { ElMessage } from 'element-plus'

export default {
  props: {
    lat: {
      type: Number,
      default: 0
    },
    lng: {
      type: Number,
      default: 0
    },
    address: {
      type: String,
      default: ''
    },
    dialogVisible: {
      type: Boolean,
      default: false
    }
  },
  emits: ['sure', 'change'],

  setup(props, ctx) {
    var map = null // 地图
    var markerLayer = null// 点标记
    const vueConfig = reactive({
      dialogAddressVisible: false,
      address: '', // 地址
      lat: 0,
      lng: 0,
      key: '你申请的key值',
      ispan: false,
      location: {}// 地址详情
    })

   

    watch(
      () => props.dialogVisible,
      () => {
        vueConfig.dialogAddressVisible = props.dialogVisible
        vueConfig.address = props.address
        vueConfig.lat = props.lat
        vueConfig.lng = props.lng
        nextTick(() => {
          if (vueConfig.dialogAddressVisible) {
            if (!props.lat) {
              getNowLngAndLat() //根据ip获取当前位置
            } else {
              getinitChange(props.lat, props.lng)//初始化地图
            }
          }
        })
      },
      { immediate: true }
    )

    // 关键字查询
    const querySearch = (queryString, callback) => {
      const url = 'https://apis.map.qq.com/ws/place/v1/suggestion' // 关键字查询
      jsonp(url, {
        key: vueConfig.key,
        keyword: queryString,
        output: 'jsonp'
      })
        .then(res => {
          if (res.status == 0) {
            const list = res.data
            callback(list)
          } else {
            ElMessage({
              type: 'error',
              message: res.message
            })
          }
        })
    }
    // 选择地址
    const handleSelect = (item) => {
      vueConfig.lat = item.location.lat
      vueConfig.lng = item.location.lng
      vueConfig.location = item
      vueConfig.ispan = false
      setInitChange()
    }
    // 修改地图位置
    const setInitChange = () => {
      map.setCenter(new window.TMap.LatLng(vueConfig.lat, vueConfig.lng))
      markerLayer.updateGeometries([
        {
          'styleId': 'myStyle',
          'id': '1',
          'position': new window.TMap.LatLng(vueConfig.lat, vueConfig.lng)
        }
      ])
    }

    // 获取当前位置
    const getNowLngAndLat = () => {
      const url = 'https://apis.map.qq.com/ws/location/v1/ip'
      jsonp(url, {
        key: vueConfig.key,
        output: 'jsonp'
      })
        .then(res => {
          if (res.status == 0) {
            vueConfig.lat = res.result.location.lat
            vueConfig.lng = res.result.location.lng
            getinitChange(vueConfig.lat, vueConfig.lng)
          } else {
            ElMessage({
              type: 'error',
              message: res.message
            })
          }
        })
    }

    // 逆解析地址
    const getInverseAnalysis = () => {
      const location = `${map.getCenter().lat},${map.getCenter().lng}`
      const url = 'https://apis.map.qq.com/ws/geocoder/v1/?location='
      jsonp(url, {
        location: location,
        output: 'jsonp',
        key: vueConfig.key
      })
        .then(res => {
          if (res.status == 0) {
            if (vueConfig.ispan) {
              vueConfig.lat = res.result.location.lat
              vueConfig.address = res.result.formatted_addresses.recommend
              vueConfig.lng = res.result.location.lng
            }
            vueConfig.ispan = true
          } else {
            ElMessage({
              type: 'error',
              message: res.message
            })
          }
        })
        .catch(err => {
          console.log(err)
        })
    }
    // 初始化地图/定位
    const getinitChange = (lat, lng) => {
      console.log(lat, lng)
      // 定义地图中心点坐标
      const myLatlng = new window.TMap.LatLng(lat, lng)
      vueConfig.lat = lat
      vueConfig.lng = lng
      // 定义map变量,调用 window.TMap.Map() 构造函数创建地图
      map = new window.TMap.Map(document.getElementById('map'), {
        center: myLatlng, // 设置地图中心点坐标
        zoom: 17.2 // 设置地图缩放级别
      })
      var geometries = {
        id: '1', // 点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
        styleId: 'myStyle', // 指定样式id
        position: myLatlng // 点标记坐标位置
      }
      markerLayer = new window.TMap.MultiMarker({
        map: map,
        styles: {
          // 创建一个styleId为"myStyle"的样式(styles的子属性名即为styleId)
          myStyle: new window.TMap.MarkerStyle({
            width: 25, // 点标记样式宽度(像素)
            height: 30 // 点标记样式高度(像素)
          })
        },
        // 点标记数据数组
        geometries: [geometries]
      })
      // 监听地图正在平移的状态
      map.on('pan', function() {
        markerLayer.updateGeometries([
          {
            'styleId': 'myStyle',
            'id': '1',
            'position': map.getCenter()
          }
        ])
      })
      // 监听地图结束平移
      map.on('panend', function() { // 拖拽结束时获取地址
        getInverseAnalysis()
      })
    }
    const resetFormData = () => { //清空地图
      map = null
      markerLayer = null
    }

    const handleClose = () => { //关闭
      resetFormData()
      ctx.emit('change', null)
    }

    const confirmMap = () => {//确认地址
      const location = {
        lat: vueConfig.lat,
        lng: vueConfig.lng,
        address: vueConfig.address
      }
      if (!vueConfig.address) {
        ElMessage({
          type: 'warning',
          message: '请获取地址/经纬度'
        })
        return false
      }

      ctx.emit('sure', location)
    }

    return {
      vueConfig,
      getinitChange,
      handleSelect,
      querySearch,
      setInitChange,
      map,
      markerLayer,
      confirmMap,
      getInverseAnalysis,
      handleClose,
      resetFormData
    }
  }
}
</script>

  <style lang="scss" scoped>
  .map-input {
    margin-bottom: 20px;
    display: flex;

    :deep(.el-autocomplete) {
      width: 100%;
    }
  }

  .map {
    position: relative;
  }

  .biadian {
    position: absolute;
    top: calc(50% - 25px);
    left: 50%;
    transform: translate(-50%, -50%);
    width: 50px;
    height: 50px;
  }
  </style>

おすすめ

転載: blog.csdn.net/sxmzhw/article/details/130742455
おすすめ