vuejs 引入高德地图 点击选取位置获取经纬度及位置信息

高德地图集成与经纬度获取

父组件:

 

 <el-form-item label="经纬度:" prop="longitude">
                    <template>
                        <div style="display: flex;align-items: center;">
                            <el-input :value="dialogForm.longitude" placeholder="经度" maxlength="30" clearable
                                @focus="getLocation" />
                            <el-input :value="dialogForm.latitude" placeholder="纬度" maxlength="30" clearable
                                @focus="getLocation" />
                        </div>
                        <quedeMap ref="mapContainer" :longitude="dialogForm.longitude" :latitude="dialogForm.latitude"
                            @getChildDate="getChildDate" />
                    </template>
                </el-form-item>

methods:

  getLocation() {
            this.$refs.mapContainer.initMap();
        },
        // 子组件传值
        getChildDate(e) {
            console.log("🚀 ~ getChildDate ~ e:", e);
            // this.childrenValue = e;
            this.dialogForm.longitude = e.longitude;
            this.dialogForm.latitude = e.latitude;
        },

封装组件: 

<template>
    <el-dialog :title="!dataForm.id ? '新建' : isDetail ? '详情' : '编辑'" :close-on-click-modal="false" :visible.sync="visible"
        class="rv-dialog rv-dialog_center" lock-scroll :modal="false" width="74%">
        <el-row :gutter="15" class="">
            <el-col :span="8">
                <el-form ref="elForm" :model="dataForm" :rules="rules" size="small" label-width="70px"
                    label-position="right" :disabled="!isDetail">
                    <el-col :span="24">
                        <el-form-item label="地点" prop="kqLocation">
                            <el-input v-model="dataForm.kqLocation" placeholder="自动带出" clearable :style="{ width: '100%' }"
                                disabled>
                            </el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="24">
                        <el-form-item label="经度" prop="kqLongitude">
                            <el-input v-model="dataForm.kqLongitude" placeholder="自动带出" clearable :style="{ width: '100%' }"
                                disabled>
                            </el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="24">
                        <el-form-item label="纬度" prop="kqLatitude">
                            <el-input v-model="dataForm.kqLatitude" placeholder="自动带出" clearable :style="{ width: '100%' }"
                                disabled>
                            </el-input>
                        </el-form-item>
                    </el-col>
                </el-form>
            </el-col>
            <el-col :span="16">
                <div style="width: 100%">
                    <div class="search_box">
                        <div class="label">关键字搜索</div>
                        <el-input v-model="input" placeholder="请输入内容" id="tipinput"></el-input>
                    </div>
                    <div ref="gaodeMap" id="gaodeMap"></div>
                </div>
            </el-col>
        </el-row>
        <span slot="footer" class="dialog-footer">
            <el-button @click="visible = false">取 消</el-button>
            <el-button type="primary" @click="dataFormSubmit()" v-if="!isDetail">确 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader"; //引入AMapLoader
window._AMapSecurityConfig = {
    // 设置安全密钥
    securityJsCode: "db177af20b348f454724fbb3c4283814",
};
export default {
    components: {},
    props: {
        longitude: {
            type: Number,
            default: 108.947089,
        },
        latitude: {
            type: Number,
            default: 34.259365,
        },
    },
    data() {
        return {
            loading: false,
            visible: false,
            isDetail: false,
            addressName: "",
            dataForm: {
                kqLocation: undefined,
                kqLongitude: undefined,
                kqLatitude: undefined,
                kqWorkUnit: undefined,
                cronkqAccredit: [],
                kqValidCardRange: undefined,
            },
            rules: {},
            input: "",
            map: null,
            auto: null,
            placeSearch: null,
            lnglat: [],
            markers: [],
            position: {},
        };
    },
    computed: {},
    watch: {},
    created() { },
    mounted() { },
    methods: {
        // 提交
        dataFormSubmit() {
            console.log("🚀 ~ dataFormSubmit ~ this.position:", this.position);
            this.$emit("getChildDate", this.position);
            this.visible = false;
        },

        // 地图初始化
        initMap() {
            console.log("🚀 ~ initMap ~ ");
            this.$nextTick(() => {
                this.visible = true;
                let centerLen = [];

                if (
                    this.longitude !== null &&
                    this.latitude !== null &&
                    this.longitude !== "" &&
                    this.latitude !== ""
                ) {
                    centerLen = [this.longitude, this.latitude];
                } else {
                    centerLen = ["108.947089", "34.259365"];
                }
                console.log("🚀 ~ this.$nextTick ~ centerLen:", centerLen);
                AMapLoader.reset()
                AMapLoader.load({
                    key: "cd5cfbe908d53292546b08959deff486", // 申请好的Web端开发者Key,首次调用 load 时必填
                    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
                    plugins: ["AMap.AutoComplete", "AMap.PlaceSearch", "AMap.Geocoder"],
                })
                    .then((AMap) => {
                        if (AMap && document.getElementById("gaodeMap")) {
                            this.map = new AMap.Map("gaodeMap", {
                                // 设置地图容器id
                                viewMode: "3D", //  是否为3D地图模式
                                zoom: 18, // 初始化地图级别
                                center: centerLen, //中心点坐标
                                resizeEnable: true,
                            });
                            this.setMarker(centerLen);
                            // 关键字查询
                            this.searchMap();
                            // 监听鼠标点击事件
                            this.map.on("click", this.clickMapHandler);
                        }
                    })
                    .catch((err) => {
                        console.log("🚀 ~ initMap ~ err:", err);
                    });
            });
        },
        // 关键字查询
        searchMap() {
            // 搜索框自动完成类
            this.auto = new AMap.AutoComplete({
                input: "tipinput", // 使用联想输入的input的id
            });
            //构造地点查询类
            this.placeSearch = new AMap.PlaceSearch({
                map: this.map,
            });
            // 当选中某条搜索记录时触发
            this.auto.on("select", this.selectSite);
        },
        //选中查询出的记录
        selectSite(e) {
            console.log("🚀 ~ selectSite ~ e:", e);
            // if (e.poi.location) {
            // this.lnglat = [e.poi.location.lng, e.poi.location.lat];
            this.placeSearch.setCity(e.poi.adcode);
            this.placeSearch.search(e.poi.name); //关键字查询
            let geocoder = new AMap.Geocoder({});
            let that = this;
            geocoder.getAddress(this.lnglat, function (status, result) {
                if (status === "complete" && result.regeocode) {
                    that.province = result.regeocode.addressComponent.province;
                    that.city = result.regeocode.addressComponent.city;
                    //自己想要赋的值,根据自己的做修改
                    that.$set(that.form, "province", that.province);
                    that.$set(that.form, "city", that.city);
                    that.$set(that.form, "address", e.poi.name);
                    that.$set(
                        that.form,
                        "coordinate",
                        e.poi.location.lng + "," + e.poi.location.lat
                    ); //纬度,经度
                } else {
                }
            });
            // } else {
            //   this.$message.error("查询地址失败,请重新输入地址");
            // }
        },
        // 点击地图事件获取经纬度,并添加标记
        clickMapHandler(e) {
            this.dataForm.kqLongitude = e.lnglat.getLng();
            this.dataForm.kqLatitude = e.lnglat.getLat();
            this.lnglat = [e.lnglat.getLng(), e.lnglat.getLat()];
            this.setMarker(this.lnglat);
            // 点击地图上的位置,根据经纬度转换成详细地址
            let geocoder = new AMap.Geocoder({});
            let that = this;
            geocoder.getAddress(this.lnglat, function (status, result) {
                if (status === "complete" && result.regeocode) {
                    console.log("🚀 ~ result:", result);
                    that.dataForm.kqLocation = result.regeocode.formattedAddress;
                }
            });
            this.position = {
                longitude: e.lnglat.getLng(),
                latitude: e.lnglat.getLat(),
                address: that.dataForm.kqLocation,
            };

            this.input = that.dataForm.kqLocation; //把查询到的地址赋值到输入框
        },
        //  添加标记
        setMarker(lnglat) {
            this.removeMarker();
            let marker = new AMap.Marker({
                position: lnglat,
            });
            marker.setMap(this.map);
            this.markers.push(marker);
        },
        // 删除之前后的标记点
        removeMarker() {
            if (this.markers) {
                this.map.remove(this.markers);
            }
        },
    },
};
</script>
   
   
<style lang="scss">
.search_box {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    height: 50px;

    .label {
        color: #000;
        width: 100px;
    }
}

.content {
    position: relative;
}

#panel {
    position: absolute;
    top: 50px;
    right: 20px;
}

#gaodeMap {
    overflow: hidden;
    width: 100%;
    height: 540px;
    margin: 0;
}

.amap-sug-result {
    z-index: 2999 !important;
}
</style>

<think>嗯,用户这次的问题是关于在uniapp中使用高德地图时,点击@tap事件无法获取经纬度的解决方案。我需要结合用户提供的三个引用内容来分析问题。 用户引用的内容很有参考价值。引用[1]展示了基本的高德地图集成方式,引用[2]提到了点击获取经纬度的需求,引用[3]则提到了两种位置选择方案。但用户明确表示这些引用不是最终需求,核心问题是@tap事件失效。 从技术角度看,这可能是几个关键问题:首先是uniapp的map组件本身没有内置点击事件返回经纬度的功能,这点很重要;其次是用户可能在错误的事件上绑定监听;还有就是高德地图API的初始化方式可能影响功能实现。 考虑到uniapp的特性,map组件的@tap事件默认只返回屏幕坐标而非经纬度,这是关键差异。解决方案应该围绕如何转换坐标展开:一是使用高德地图的convertFrom方法进行坐标转换;二是考虑改用更专业的@regionchange事件。 用户可能已经尝试过简单绑定@tap事件但发现返回数据不符合预期,说明ta对地图坐标转换机制不太熟悉。需要特别强调坐标转换这个技术点,因为引用内容里完全没有提到这点。 另外注意到引用[3]提到的uni.chooseLocation方案,虽然能解决问题但会跳转新页面,可能不符合用户"在当前页面交互"的需求,所以作为备选方案更合适。 在给出代码示例时,要确保包含完整的坐标转换逻辑,特别是amapFun.getRegeo方法的调用细节。同时要提醒用户注意异步处理,因为地图API调用都是异步的。 最后要解释为什么需要创建mapContext对象——因为uniapp的map组件控制依赖这个对象,这点在引用[1]的代码片段里有体现但没说明作用。 </think>在 UniApp 中使用高德地图时,`@tap` 事件默认返回的是屏幕坐标(`{x, y}`),**而非经纬度坐标**。要解决点击地图获取经纬度失效的问题,需要调用高德地图 API 进行坐标转换: ### 解决方案步骤 1. **正确绑定事件 & 获取屏幕坐标:** ```html <template> <map id="my-map" :latitude="latitude" :longitude="longitude" @tap="handleMapTap" <!-- 绑定点击事件 --> ></map> </template> <script> // ... 引入 amap-wx.js 和初始化 myAmapFun 的代码 ... export default { methods: { async handleMapTap(e) { // 1. 获取点击事件的屏幕坐标 (e.detail) const screenX = e.detail.x || e.detail.longPress?.[0]?.x; // 兼容普通点击和长按 const screenY = e.detail.y || e.detail.longPress?.[0]?.y; if (screenX === undefined || screenY === undefined) { console.error('无法获取点击屏幕坐标', e.detail); return; } // ... 后续步骤 ... } } } </script> ``` 2. **使用高德 API 转换屏幕坐标为经纬度:** ```javascript handleMapTap(e) { // ... 获取 screenX, screenY 代码 ... // 2. 获取 MapContext (确保在 onReady 或之后调用) const mapCtx = uni.createMapContext('my-map', this); // ID 需匹配 map 标签的 id // 3. 调用高德 API 将屏幕坐标转为经纬度 try { // 关键步骤:调用 convertFrom 方法 const res = await new Promise((resolve, reject) => { myAmapFun.getRegeo({ location: `${screenX},${screenY}`, // 传入屏幕坐标 success: resolve, fail: reject }); }); // 4. 从回调结果中获取经纬度 if (res && res[0] && res[0].longitude && res[0].latitude) { const longitude = res[0].longitude; // 经度 const latitude = res[0].latitude; // 纬度 const address = res[0].name; // 可选:大致位置描述 console.log('点击位置经纬度:', longitude, latitude, address); // 5. 更新 data 或执行后续操作 this.longitude = longitude; this.latitude = latitude; // ... 其他业务逻辑(如显示标记、跳转等)... } else { console.error('坐标转换失败,返回数据异常:', res); } } catch (err) { console.error('调用 getRegeo 转换坐标失败:', err); } } ``` ### 关键点说明 1. **`@tap` 事件返回屏幕坐标:** `e.detail` 包含的是点击点在屏幕上的像素位置 (`x`, `y`),不是经纬度[^2]。 2. **必须使用高德 API 转换:** `myAmapFun.getRegeo` 是高德地图提供的将**屏幕坐标**转换为**经纬度坐标**的核心方法[^1][^2]。 3. **`mapContext` 的作用:** `uni.createMapContext` 获取的是 UniApp 的 MapContext 对象,用于调用 UniApp 提供的原生地图控件方法(如移动视野)。转换坐标**必须依赖高德 API (`getRegeo`)**,而非 MapContext。 4. **异步处理:** `getRegeo` 是异步操作,使用 `Promise` 或 `async/await` 处理更清晰。 5. **错误处理:** 务必添加 `try...catch` 和结果有效性检查,确保转换成功。 6. **权限与 Key:** 确保已正确配置高德地图的 Key 且无错误,并在高德控制台开通了相应权限(通常 `getRegeo` 需要逆地理编码或定位服务权限)。 ### 备选方案:使用 `@regionchange` (推荐) 如果点击目的是为了移动地图获取中心点经纬度,`@tap` + 转换可能并非最佳。改用 `@regionchange` 事件更高效: ```html <map id="my-map" :latitude="latitude" :longitude="longitude" @regionchange="handleRegionChange" <!-- 地图视野变化时触发 --> ></map> ``` ```javascript handleRegionChange(e) { if (e.type === 'end') { // 只在视野变化结束时获取 this.mapContext = this.mapContext || uni.createMapContext('my-map', this); this.mapContext.getCenterLocation({ success: (res) => { this.longitude = res.longitude; this.latitude = res.latitude; console.log('地图中心点经纬度:', res.longitude, res.latitude); }, fail: (err) => { console.error('获取中心点失败:', err); } }); } } ``` 此方式性能更优,且无需调用高德 API 转换坐标,直接通过 `getCenterLocation` 获取中心点经纬度[^2][^3]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值