3***@qq.com
3***@qq.com
  • 发布:2025-03-03 10:42
  • 更新:2025-03-03 10:42
  • 阅读:72

map在浏览器运行的时候可以缩放和拖动,在微信开发者工具里运行时却不可以

分类:uni-app
<template> <view class="container"> <!-- 地图 --> <map id="myMap" class="map" latitude="latitude" longitude="longitude" markers="markers" enable-zoom="true" enable-scroll="true" show-location

scale="mapScale"> </map>

<!-- 主弹出层 -->  
<uni-popup ref="popup" mask-background-color="rgba(0,0,0,0)" type="bottom" :is-mask-click="false"  
animation="false"> <view class="main-popup-content popup-content">
<!-- 弹出层内容 -->
<view class="header">
<scroll-view class="nav-scroll" scroll-x>
<view class="nav-item" v-for="(item, index) in groups" :key="item.id"

class="{active: activeIndex === index}" @click="switchGroup(index)"> {{item.name}}
</view>
<view class="add-btn" @click="addGroup">

  • 新增分组
    </view>
    </scroll-view>
    <text class="edit-icon" @click="showGroupManager">✎</text>
    </view>

        <!-- 中间内容区域 -->  
        <view class="content" v-if="currentPlaces.length">  
            <view class="place-item" v-for="item in currentPlaces" :key="item.id">  
                <view class="info">  
                    <text class="name">{{item.name}}</text>  
                    <text class="distance">{{item.distance}}</text>  
                </view>  
                <text class="tag">{{item.tag}}</text>  
            </view>  
        </view>  
    
        <!-- 底部栏 -->  
        <view class="footer" v-if="currentPlaces.length">  
            <button class="btn">智能路线规划</button>  
            <button class="btn add-btn">+ 添加地点</button>  
        </view>  
    
        <view class="empty" v-else>  
            <image src="../../static/images/empty.jpg" mode="aspectFill"></image>  
            <button @click="openAddLocationPopup"><uni-icons type="location" size="18" color="#007AFF"></uni-icons>添加地点</button>  
        </view>  
    
    </view>  

    </uni-popup>

    <!-- 分组管理弹出层 -->
    <uni-popup ref="manageGroupPopup" type="bottom">
    <view class="manageGroupPopup-content popup-content">
    <view class="group-title">
    <text class="title">分组列表</text>
    <uni-icons type="clear" size="28" color="#ddd" @click="closeManageGroupPopup"></uni-icons>
    </view>
    <view class="group-list">
    <view class="group-item"
    v-for="(item, index) in groups"

key="item.id"> <uni-icons type="minus-filled" size="26" color="red" v-if="groups.length > 1" @click="iconClick"></uni-icons>
<input class="uni-input" type="text" v-model="item.name"/>
<uni-icons type="bars" size="26"></uni-icons>
</view>
<view class="add-group" @click="addGroup">
<uni-icons type="plus-filled" size="26" color="blue"></uni-icons>
<text class="text">新增分组</text>
</view>
</view>
</view>
</uni-popup>

<!-- 添加地点弹出层 -->  
<uni-popup ref="addLocationPopup" type="bottom" mask-background-color="rgba(0,0,0,0)" animation>  
    <view class="addLocationPopup-content popup-content">  
        <view class="head">  
            <view class="location">  
                <uni-icons type="location" size="22" color="white"></uni-icons>  
                <text class="text">{{area}}<uni-icons type="down" size="16" color="white"></uni-icons></text>  
            </view>  
            <text class="middle">添加新地点</text>  
            <view class="close">  
                <uni-icons type="clear" size="28" color="#969694" @click="closeAddLocationPopup"></uni-icons>  
            </view>  
        </view>  
        <view class="tabs">  
            <view class="tab-item" v-for="(item,index) in tabList" :key="item.icon" :class="{'tabActivited': activeTabIndex === index}">  
                <uni-icons :class="{'tabActivitedIcon': activeTabIndex === index}" :type=item.icon size="30" color="#91928c"></uni-icons>  
                <view class="text">{{item.text}}</view>  
            </view>  
        </view>  
        <view class="search">  
            <view class="search-input">  
                <uni-icons class="left-icon" type="search" size="26" color="#eee"></uni-icons>  
                <input class="input" type="text" placeholder="开始搜索地点" v-model="searchArea" @confirm="handleConfirm" focus/>  
                <uni-icons class="right-icon" v-if="searchArea" type="clear" size="20" @click="clearSearchArea" color="#91928c"></uni-icons>  
            </view>  
            <view v-if="!noSearch || !searchArea">  
                <view class="latestSearch" v-if="!searchArea || searchResult.length === 0">  
                    <view class="title">最近搜索</view>  
                    <view v-if="latestSearchList.length > 0" class="search-list">  
                        <view class="search-item" v-for="(item,index) in latestSearchList" :key="index">  
                            <view class="left-icon">  
                                <uni-icons type="map-pin-ellipse" size="20" color="#ddd"></uni-icons>  
                            </view>  
                            <view class="name"  @click="clickHistoryItem(item)">{{item}}</view>  
                            <view class="right-icon">  
                                <uni-icons type="close" size="20" color="#ddd" @click="deleteArea(index)"></uni-icons>  
                            </view>  
                        </view>  
                    </view>  
                    <view v-else class="empty">暂无搜索记录</view>  
                </view>  
                <!-- 搜索结果列表 -->  
                <scroll-view   
                    scroll-y  
                    class="result-list"  
                    v-if="searchArea && searchResult.length > 0"  
                    style="{ 'overflow: hidden; -webkit-overflow-scrolling: touch; }"  
                >  
                    <view v-for="(item, index) in searchResult" :key="item.id" class="result-item" @click="handleSelectLocation(item)">  
                        <view class="address">  
                            <view class="name">{{item.name}}</view>  
                            <view class="detail">{{item.address}}</view>  
                        </view>  
                        <view class="distance">{{item.distance}}km</view>  
                    </view>  
                    <view class="nosearch">  
                        搜索不到新地点?试试使用<view class="mark" @click="console.log('1111')">地图选点</view>标注吧  
                    </view>  
                    <view class="empty" style="height: 200rpx;"></view>  
                </scroll-view>  
            </view>  
            <view v-if="noSearch && searchArea" class="no-result">  
                <image src="../../static/images/emptySearchArea.png" mode="aspectFill"></image>  
                <text>暂无搜索结果</text>  
                <view class="nosearch">  
                    搜索不到新地点?试试使用<view class="mark" @click="console.log('1111')">地图选点</view>标注吧  
                </view>  
            </view>  
        </view>  
    </view>  
</uni-popup>  

<!-- 编辑选中地点详情弹出层 -->  
<uni-popup ref="editLocationDetailPopup" type="bottom" mask-background-color="rgba(0,0,0,0)">  
    <view class="details-content popup-content">  
        <view class="head">  
            头头头头头头头头头头头头头头头头头头头头头头头头头头头  
        </view>  
    </view>  
</uni-popup>>  

<!-- 悬浮控件 -->  
<view class="floating-controls popup-content">  
    <button @click="toggleFullscreen">{{isFullscreenText}}</text></button>  
    <button @click="openSettings" v-if="!isFullscreen">调节</button>  
</view>  

<!-- 设置弹出层 -->  
<uni-popup ref="settingsPopup" type="bottom" v-bind:mask="false">  
    <view class="settings-content popup-content">  
        <text>风格调整</text>  
        <text>模式切换</text>  
        <text>设置</text>  
        <text>标记</text>  
        <text>路线</text>  
        <text>标题</text>  
        <text>VIP</text>  
        <text>经典图册</text>  
        <text>排序</text>  
        <text>EMOJI</text>  
        <button @click="closeSettings">取消</button>  
        <button @click="saveSettings">保存</button>  
    </view>  
</uni-popup>  

</view>
</template>

<script>
import { getCoordinateAPI, getSearchLocation } from '@/api/city/index.js'
export default {
data() {
return {
isOpen: true,
mapScale: 16,
latitude: 39.90469, // 地图纬度
longitude: 116.40717, // 地图经度
markers: [], // 地图标记
popupHeight: 800, // 弹出层高度
isFullscreen: false, // 是否全屏
isFullscreenText: '全屏',
area: '北京',
activeIndex: 0,
groups: [{
id: 1,
name: '分组1'
}],
places: [],
isSorting: true,
tabList: [
{icon: 'search', text: '搜索'},
{icon: 'shop-filled', text: '酒店特惠'},
{icon: 'scan', text: '智能解析'},
{icon: 'location-filled', text: '地图选点'}
],
activeTabIndex: 0,
searchArea: '',
searchResult: [],
noSearch: false,
latestSearchList: uni.getStorageSync("historySearch") || [],
selectedLocation: null, // 选中的地点信息
};
},
onLoad(e) {
let {
area = null
} = e
if (area) {
this.area = area
}
this.getCoordinate()
this.$nextTick(() => {
this.$refs.popup.open();
});
},
computed: {
currentPlaces() {
return this.places[this.groups[this.activeIndex].id] || []
}
},
methods: {
// 获取哪个地点的地图渲染
async getCoordinate() {
const res = await getCoordinateAPI(this.area)
this.latitude = res.data.latitude,
this.longitude = res.data.longitude
},
// 切换全屏
toggleFullscreen() {
console.log('1111')
this.isFullscreen = !this.isFullscreen;
if (this.isFullscreen) {
this.isFullscreenText = '退出'
this.$refs.popup.close();
} else {
this.isFullscreenText = '全屏'
this.$refs.popup.open();
}
},
// 打开设置弹出层
openSettings() {
this.$refs.settingsPopup.open();
},
// 关闭设置弹出层
closeSettings() {
this.$refs.settingsPopup.close();
},
// 保存设置
saveSettings() {
this.closeSettings();
},
// 切换添加地点
toggleAddLocation() {
this.popupHeight = this.popupHeight === 200 ? 400 : 200;
},
// 添加分组
addGroup() {
const newId = Date.now()
this.groups.push({
id: newId,
name: 分组${this.groups.length + 1}
})
this.places[newId] = []
},
// 切换分组
switchGroup(index) {
this.activeIndex = index
},
// 打开分组管理弹出层
showGroupManager () {
this.$refs.manageGroupPopup.open()
},
// 关闭分组管理弹出层
closeManageGroupPopup () {
this.$refs.manageGroupPopup.close()
},
// 点击删除分组的图标
iconClick(index) {
uni.showModal({
title:'提示',
content: '是否确认删除,删除分组后地点将无法恢复',
success: (res) => {
if (res.confirm) {
this.groups.splice(index,1)
}
}
})
},
// 打开添加地点弹出层
openAddLocationPopup () {
this.$refs.addLocationPopup.open()
},
// 关闭添加地点弹出层
closeAddLocationPopup () {
this.$refs.addLocationPopup.close()
},
// 清空搜索框内的内容
clearSearchArea () {
this.searchArea = ''
this.searchResult = ''
this.noSearch = false
},
// 确认搜索
async handleConfirm () {
if (this.searchArea.trim() !== '') {
this.latestSearchList = [...new Set([this.searchArea, ...this.latestSearchList])]
uni.setStorageSync("historySearch", this.latestSearchList)
}else {
uni.showToast({
title:"搜索的内容不能为空",
icon:"none"
})
}
const res = await getSearchLocation(this.searchArea, this.latitude, this.longitude)
this.searchResult = res.data.results
if (this.searchResult.length === 0) {
this.noSearch = true
console.log(this.noSearch)
}else {
this.noSearch = false
}
},
// 删除搜索历史中的某个记录
deleteArea (index) {
this.latestSearchList.splice(index,1)
uni.setStorageSync("historySearch", this.latestSearchList)
},
// 点击搜索历史中某条记录
clickHistoryItem(item) {
this.searchArea = item
this.latestSearchList = [...new Set([this.searchArea, ...this.latestSearchList])]
uni.setStorageSync("historySearch", this.latestSearchList)
this.handleConfirm()
},
// 点击搜索返回的结果列表中的某个地点
handleSelectLocation(item) {
console.log(item)
try {
this.latitude = item.poiLatitude
this.longitude = item.poiLongitude
this.makers = [{
id: Date.now(),
latitude: item.poiLatitude,
longitude: item.poiLongitude,
title: item.name,
iconPath: '../../static/redMaker.png'
}]

                this.selectedLocation = item  
                this.$refs.addLocationPopup.close()  
                this.$refs.editLocationDetailPopup.open()  
            }catch{  

            }  
        }  
    }  
}  

</script>

<style scoped lang="scss">
.container {
position: relative;
height: 100vh;
isolation: isolate;
}

.map {  
    width: 100vw;  
    height: 100vh;  
    position: fixed;  
    top: 0;  
    left: 0;  
    z-index: 0; /* 确保地图在底层 */  
    transition: all 0.3s;  
    transform: translateZ(0); /* 解决iOS滑动卡顿 */  
}  

.main-popup-content {  
    background-color: #fafafa;  
    border-radius: 20px 20px 0 0;  
    padding: 20px;  
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);  
    min-height: 600rpx;  
    // transition: height 0.3s ease;  
    z-index: 900;  
    position: fixed;  
    bottom: 0;  
    left: 0;  
    right: 0;  

    .header {  
        display: flex;  
        align-items: center;  
        justify-content: space-between;  
        background: #fafafa;  
        border-bottom: 1px solid #eee;  
    }  

    .nav-scroll {  
        white-space: nowrap;  
        width: 624rpx;  
    }  

    .nav-item {  
        flex: 1;  
        display: inline-block;  
        padding: 8px 15px;  
        margin-right: 10px;  
        border-radius: 16px;  
        background-color: #ddd;  
        color: #777;  

        &.active {  
            background: #007AFF;  
            color: white;  
        }  
    }  

    .add-btn {  
        display: inline-block;  
        border-radius: 16px;  
        padding: 8px 15px;  
        background-color: #fff;  
        border: 1px solid #ddd;  
        color: #555;  
    }  

    .edit-icon {  
        padding: 0 10px;  
        font-size: 18px;  
    }  

    .content {  
        flex: 1;  
        padding: 15px;  
    }  

    .footer {  
        padding: 10px;  
        background: #fff;  
        display: flex;  
        gap: 10px;  
        box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);  
    }  

    .btn {  
        flex: 1;  
        background: #007AFF;  
        color: white;  

        &.add-btn {  
            background: #4CD964;  
        }  
    }  
    .empty {  
        display: flex;  
        flex-direction: column;  
        align-items: center;  
        padding: 20px;  
        button {  
            height: 70rpx;  
            width: 250rpx;  
            line-height: 70rpx;  
            background-color: #eee;  
            color: #007AFF;  
            border: none;  
            display: flex;  
            align-items: center;  
            justify-content: center;  
            font-size: 16px;  
            .uni-icons {  
                margin-right: 5px;  
            }  
        }  
    }  
}  

.manageGroupPopup-content {  
    min-height: 800rpx;  
    z-index: 901;  
    background-color: #fff;  
    border-radius: 20px 20px 0 0;  
    padding: 20px;  
    position: fixed;  
    bottom: 0;  
    left: 0;  
    right: 0;  

    .group-title {  
        display: flex;  
        justify-content: space-between;  
        .title {  
            font-size: 20px;  
            font-weight: 600;  
            margin-bottom: 8rpx;  
        }  
    }  

    .group-list {  
        background-color: #fafafa;  
        border-radius: 10px;  
        padding: 0 10px;  
        .group-item {  
            width: 100%;  
            height: 100rpx;  
            align-items: center;  
            display: flex;  
            justify-content: space-between;  
            margin-top: 5px;  
            .uni-input {  
                width: 500rpx;  
                height: 50rpx;  
                border-bottom: 1px solid #eee;  
            }  
        }  
        .add-group {  
            width: 100%;  
            height: 100rpx;  
            display: flex;  
            align-items: center;  
            .text {  
                margin-left: 8px;  
            }  
        }  
    }  
}  

.addLocationPopup-content {  
    background-color: #2a2a2a;  
    z-index: 902;  
    height: 1330rpx;  
    height: 80vh;  
    border-radius: 30px 30px 0 0;  
    padding: 10px;  
    color: #fff;  
    position: fixed;  
    bottom: 0;  
    left: 0;  
    right: 0;  
    .head {  
        display: flex;  
        align-items: center;  
        .location {  
            flex: 4;  
            .text {  
                margin-left: 2px;  
                overflow: hidden;  
            }  
        }  
        .middle {  
            font-size: 18px;  
            flex: 5;  
        }  
        .close {  
            flex: 1;  
            color: #91928c;  
        }  
    }  
    .tabs {  
        margin-top: 20px;  
        color: #91928c;  
        display: flex;  
        justify-content: space-between;  
        align-items: center;  
        padding: 0 10px;  
        border-bottom: 1px solid #91928d;  
        .tab-item {  
            display: flex;  
            flex-direction: column;  
            align-items: center;  
            .text {  
                padding: 10px 0;  
            }  
        }  
    }  
    .search {  
        padding: 20px;  
        height: calc(100% - 120px);  
        display: flex;  
        flex-direction: column;  
        overflow: hidden;  
        .search-input {  
            display: flex;  
            align-items: center;  
            justify-content: space-between;  
            border: 1px solid #91928c;  
            width: 640rpx;  
            height: 90rpx;  
            border-radius: 20px;  
            padding: 0 10rpx;  
            .left-icon {  
                flex: 4;  
            }  
            .input {  
                flex: 20;  
                background-color: rgba(0,0,0,0);  
            }  
            .right-icon {  
                flex: 3;  
            }  
        }  
        .latestSearch {  
            margin-top: 40rpx;  
            .title {  
                font-size: 40rpx;  
                font-weight: 600;  
                color: #ddd;  
            }  
            .search-list {  
                .search-item {  
                    margin: 15rpx 0;  
                    display: flex;  
                    align-items: center;  
                    font-size: 35rpx;  
                    .left-icon {  
                        flex: 1;  
                    }  
                    .name {  
                        flex: 8;  
                    }  
                    .right-icon {  
                        flex: 1;  
                    }  
                }     
            }  
            .empty {  
                margin-top: 50rpx;  
                font-size: 38rpx;  
                color: #ddd;  
            }  
        }  
        .result-list {  
            flex: 1;  
            overflow: hidden;  
            height: 100%;  
            .result-item {  
                padding: 5px;  
                width: 100%;  
                height: 150rpx;  
                border-bottom: 1px solid rgba(145,146,140,0.5);  
                display: flex;  
                align-items: center;  
                justify-content: space-around;  
                .address {  
                    display: flex;  
                    flex-direction: column;  
                    color: #f4f4f4;  
                    width: 440rpx;  
                    overflow: hidden;  
                    text-overflow: ellipsis;  
                    white-space: nowrap;  
                    .name {  
                        font-size: 44rpx;  
                        margin-bottom: 10rpx;  
                        overflow: hidden;  
                        text-overflow: ellipsis;  
                        white-space: nowrap;  
                    }  
                    .address {  
                        font-size: 22rpx;  
                        width: 100%;  
                        overflow: hidden;  
                        text-overflow: ellipsis;  
                        white-space: nowrap;  
                    }  
                }  
                .distance {  
                    color: #f4f4f4;  
                    font-size: 28rpx;  
                }  
            }  
            .nosearch {  
                display: flex;  
                align-items: center;  
                justify-content: center;  
                color: #ccc;  
                font-size: 26rpx;  
                margin-top: 50rpx;  
                .mark {  
                    color: white;  
                    font-size: 28rpx;  
                    margin: 0 6rpx;  
                }  
            }  
        }  
        .no-result {  
            height: 900rpx;  
            margin: 0 auto;  
            display: flex;  
            flex-direction: column;  
            align-items: center;  
            image {  
                width: 500rpx;  
                height: 500rpx;  
            }  
            text {  
                font-size: 40rpx;  
                color: #ddd;  
            }  
            .nosearch {  
                display: flex;  
                align-items: center;  
                justify-content: center;  
                color: #ccc;  
                font-size: 26rpx;  
                margin-top: 50rpx;  
                .mark {  
                    color: white;  
                    font-size: 28rpx;  
                    margin: 0 6rpx;  
                }  
            }  
        }  
    }  
}  

.details-content {  
    background-color: white;  
    z-index: 903;  
    height: 45vh;  
    border-radius: 30px 30px 0 0;  
    padding: 10px;  
    // position: fixed;  
    // bottom: 0;  
    // left: 0;  
    // right: 0;  
}  

.tabActivited {  
    color: white;  
    .text {  
        border-bottom: 2px solid white;  
    }  
}  
.tabActivitedIcon {  
    color: white !important;  
}  

.floating-controls {  
    position: fixed;  
    display: flex;  
    flex-direction: column;  
    justify-content: center;  
    top: 90px;  
    right: 20px;  
    gap: 5px;  
    z-index: 1;  
}  

.floating-controls button {  
    width: 110rpx;  
    height: 60rpx;  
    line-height: 60rpx;  
    font-size: 12px;  
    flex-direction: row;  
    background-color: rgb(250, 250, 250);  
    border: 1px solid #ccc;  
    border-radius: 10rpx;  
}  

.settings-content {  
    background-color: #fff;  
    padding: 20px;  
    border-radius: 20px 20px 0 0;  
}  

/* 隐藏遮罩层残留(某些版本需要) */  
.uni-popup__mask {  
    display: none !important;  
}  

/* 允许地图穿透操作 */  
.uni-popup {  
    pointer-events: none !important;  
    /* 整个弹出层不拦截事件 */  
}  

/* 内容区域需要单独响应点击 */  
.popup-content {  
    pointer-events: auto;  
    /* 内容区域可交互 */  
}  

</style>

2025-03-03 10:42 负责人:无 分享
已邀请:

要回复问题请先登录注册