vue3 Element plus 百度地图封装( 搜索定位功能,拖拽回显功能)

实现效果

在这里插入图片描述

直接代码(备注很详细的~)
<template>
    <div class="baidu_map">
        <el-form ref="form" label-suffix=":" label-width="100px">
            <el-row :gutter="10">
                <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
                    <el-form-item label="详细地址">
                        <el-autocomplete
                            style="width:100%;"
                            popper-class="autoAddressClass"
                            v-model="mapData.address"
                            :fetch-suggestions="querySearch"
                            :trigger-on-focus="false"
                            placeholder="请输入详细地址"
                            @select="handleSelect"
                            clearable
                            >
                            <template #default="{ item }">
                                <div class="autoAddressClass_item">
                                    <ElIcon :size="20" color="balck">
                                        <Search />
                                    </ElIcon>
                                    <div>
                                        <div class="title">{{ item.title }}</div>
                                        <span class="address ellipsis">{{ item.address }}</span>
                                    </div>
                                </div>
                            </template>
                        </el-autocomplete>
                    </el-form-item>
                </el-col>                
                <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
                    <el-form-item label="经纬度" prop="projectId">
                        <el-input disabled placeholder="请选择经纬度" v-model="mapData.point" type="text" :readonly="true" ></el-input>
                    </el-form-item>
                </el-col>                
            </el-row>
            <div id="map" :style="{ width, height }"></div>
        </el-form>
    </div>
</template>
   
<script setup>
import { Search } from '@element-plus/icons-vue' 
// 初始化经纬度 宽高 层级
const { latitude, longitude, width, height, zoom} = defineProps({
    latitude:{
        type:Number,
        default:36.67411054692821
    },
    longitude:{
        type: Number,
        default:117.10358591219932,
    },
    width:{
        type: String,
        default: '920px'
    },
    height:{
        type: String,
        default: '400px'
    },
    zoom:{
        type: Number,
        default: 12
    },
})
const mapData = ref({
    address:'',//详细地址
    point:'',//经纬度
    lat:'', //经度
    lng:'', //纬度
})
const emits = defineEmits(['getPoint'])

const BMap = window.BMap

let Map = null
let mk = null
onMounted(()=>{
    //初始化地图 禁用地图默认点击弹框
    Map = new BMap.Map('map',{enableMapClick:false}) 
    var point = new BMap.Point(longitude, latitude)
    // 初始化 地图经纬度 层级
    Map.centerAndZoom(point, zoom)
    Map.enableScrollWheelZoom(true)

    //创建一个图像标注实例 启用拖拽 默认为false
    mk = new BMap.Marker(point,{enableDragging:true}) 
    Map.addOverlay(mk) //将覆盖物添加到地图中
    mk.addEventListener('dragend', function(e){
        getAddrByPoint(e.point) //拖拽结束后调用逆地址解析函数,e.point为拖拽后的地理坐标
    })
    // 添加地图点击事件
    // Map.addEventListener('click', function (e) {
    //     console.log('点击的经纬度:' + e.point.lng + ',' + e.point.lat) //
    //     emits('getPoint',(e.point.lng + ',' + e.point.lat))
    // })
})
/**
 * 根据用户输入 展示可选地区
 * @param { String } str 当前用户输入 
 * @param { Function } cb 渲染回调
 */
function querySearch(str,cb){
    var options = {
        //检索完成后的回调函数
        onSearchComplete: function(res){ 
            var arr = [];
            if (local.getStatus() == BMAP_STATUS_SUCCESS){
                for (var i = 0; i < res.getCurrentNumPois(); i ++){
                    arr.push(res.getPoi(i));
                }
            }
            //获取到数据时,通过回调函数cb返回到<el-autocomplete>组件中进行显示
            cb(arr)
        }
    }
    //创建LocalSearch构造函数
    var local = new BMap.LocalSearch(Map, options)
    local.search(str) 
}

/**
 * 选择地区
 * @param { Obejct } item 
 */
function handleSelect(item){
    // 保存当前数据
    mapData.value = {
        address:item.address,
        point:item.point.lat + ',' + item.point.lng,
        lat:item.point.lat,
        lng:item.point.lng
    }
    //清除地图上所有覆盖物
    Map.clearOverlays() 
    //根据所选坐标重新创建Marker 记住打开可拖拽 默认是不打开的
    mk = new BMap.Marker(item.point,{enableDragging:true})
    mk.addEventListener('dragend', function(e){
        getAddrByPoint(e.point) //拖拽结束后调用逆地址解析函数,e.point为拖拽后的地理坐标
    })
    //将覆盖物重新添加到地图中
    Map.addOverlay(mk) 
    //将地图的中心点更改为选定坐标点
    Map.panTo(item.point) 
}
/**
 * 逆地址解析函数 根据经纬度获取详细地址
 * @param {Object} point 当前经纬度
 */
function getAddrByPoint(point){
  var geco = new BMap.Geocoder();
  geco.getLocation(point, function(res){
    mapData.value = {
        address:res.address,
        point:point.lat + ',' + point.lng,
        lat:point.lat,
        lng:point.lng
    }
    mk.setPosition(point) //重新设置标注的地理坐标
    Map.panTo(point)  //将地图的中心点更改为给定的点
  })
}
// 暴露需要的数据
defineExpose({ mapData })
</script>
   
<style scoped lang="scss">
.autoAddressClass{
  li {
    .title {
        line-height: 30px;
        text-overflow: ellipsis;
        overflow: hidden;
    }
    .address {
        line-height: 1;
        font-size: 12px;
        color: #b4b4b4;
        margin-bottom: 5px;
    }
    .autoAddressClass_item{
        overflow: hidden;
        display: flex;
        align-items: center;
        .el-icon{
            margin-right: 20px;
        }
    }
  }
}
</style>
以下是一个简单的 Vue3 Element Plus 文件上传组件封装: ```vue <template> <el-upload :class="uploadClass" :action="uploadUrl" :headers="uploadHeaders" :data="uploadData" :multiple="multiple" :limit="limit" :file-list="fileList" :auto-upload="autoUpload" :show-file-list="showFileList" :on-change="handleChange" :before-upload="beforeUpload" :on-exceed="handleExceed" :on-success="handleSuccess" :on-error="handleError" > <el-button :size="buttonSize" type="primary">{{ buttonText }}</el-button> <div slot="tip" class="el-upload__tip">{{ uploadTip }}</div> </el-upload> </template> <script> import { ref } from 'vue'; export default { props: { uploadUrl: { type: String, required: true }, uploadHeaders: Object, uploadData: Object, uploadClass: String, multiple: { type: Boolean, default: false }, limit: { type: Number, default: 3 }, fileList: { type: Array, default: () => [] }, autoUpload: { type: Boolean, default: true }, showFileList: { type: Boolean, default: true }, buttonSize: { type: String, default: 'medium' }, buttonText: { type: String, default: '点击上传' }, uploadTip: { type: String, default: '只能上传jpg/png文件,且不超过2MB' } }, setup(props, { emit }) { const uploadRef = ref(null); function handleChange(file, fileList) { emit('change', file, fileList); } function beforeUpload(file) { const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'; const isLt2M = file.size / 1024 / 1024 < 2; if (!isJPG) { this.$message.error('上传头像图片只能是 JPG/PNG 格式!'); } if (!isLt2M) { this.$message.error('上传头像图片大小不能超过 2MB!'); } return isJPG && isLt2M; } function handleExceed(files, fileList) { this.$message.warning(`当前限制选择 ${props.limit} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${fileList.length} 个文件`); } function handleSuccess(response, file, fileList) { emit('success', response, file, fileList); } function handleError(error, file, fileList) { emit('error', error, file, fileList); } // 返回需要暴露给父组件的数据和方法 return { uploadRef, handleChange, beforeUpload, handleExceed, handleSuccess, handleError }; } }; </script> ``` 这个组件的主要功能是将 Element Plus 的 Upload 组件进行封装并暴露出一些常用的事件和方法,方便在父组件中进行调用。其中,`uploadUrl` 是必传的属性,用于指定上传接口的地址。其他属性都有默认值,并可以通过传递 props 进行修改。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值