<template>
<view class="pMap">
<!-- -->
<map class="pMap-box"
id="mapContext"
:longitude="mapInstance.longitude"
:latitude="mapInstance.latitude"
:markers="markers"
:polyline="polyline"
:show-location="true"
:scale="mapScale"
:include-points="includePoints"
:polygon="polygon"
:style="{width:windowWidth+'px',height: '500rpx'}">
<cover-view class="pMap-box-callout" slot="callout">
<block v-for="(item,index) in markers" :key="index" >
<cover-view
v-if="item.customCallout"
class="pMap-box-callout-list"
:marker-id="item.id">
<cover-view class="pMap-box-callout-list-item">
<cover-view class="pMap-box-callout-list-item-center">
<cover-view class="pMap-box-callout-list-item-center-tag">
{{index == 0?'发':index == markers.length-1?'收':''}}
</cover-view>
<cover-view class="pMap-box-callout-list-item-center-txt">
{{item.title}}
</cover-view>
</cover-view>
</cover-view>
</cover-view>
</block>
</cover-view>
</map>
</view>
</template>
<script setup>
import startIcon from '@/static/image/order/map.png'
import processIcon from '@/static/image/order/car.png'
import {ref,getCurrentInstance,computed,defineExpose,onMounted, nextTick} from 'vue';
import {Config} from "@/http/config";
import {systemStore} from '@/store/system'
const {windowWidth} = systemStore();
const _this = getCurrentInstance();
const mapContext = ref(null);
onMounted(()=>{
mapContext.value = uni.createMapContext('mapContext',_this);
})
const props = defineProps({
routePoints: {
type: Array,
default: []
}
})
// 获取标记点图标
const getMarkerIconByStatus = (status) => {
switch (status) {
case 'start':
return startIcon;
case 'end':
return startIcon;
case 'process':
// return null;
return processIcon;
default:
return startIcon;
}
}
// 缓存节点颜色配置
const statusColorMap =(status)=> {
switch (status) {
case 'start':
return '#52c41a';
case 'end':
return '#52c41a';
case 'process':
return '#1890ff';
default:
return '#faad14';
}
};
// 构建标记点
const markers = computed( () => {
if (!props.routePoints || props.routePoints.length === 0) {
return []
}
return props.routePoints.map((marker, index) => {
// 根据状态设置标记点图标
let iconPath = getMarkerIconByStatus(marker.status);
let customCallout = undefined;
let width = '10px';
let height = '10px';
switch (marker.status) {
case 'start':
customCallout={
anchorY: 0,
anchorX: 0,
display:"ALWAYS",//一直展示
}
width = '28px';
height = '34px';
break;
case 'end':
customCallout ={
anchorY: 0,
anchorX: 0,
display:"ALWAYS",//一直展示
}
width = '28px';
height = '34px';
break;
case 'process':
width = '20px';
height = '15px';
break;
}
const markerId = `marker_${index}`;
// marker.id ||
return {
id: index || markerId,
longitude: marker.longitude,
latitude: marker.latitude,
title: marker.title,
iconPath,
width,
height,
customCallout,
joinCluster: true,
zIndex:1,
...marker
}
})
})
// 构建路线
const polylineId = ref('logistics-route');
const polyline = computed(() => {
if (!props.routePoints || props.routePoints.length < 2) {
return []
}
const points = props.routePoints.map(point => ({
longitude: point.longitude,
latitude: point.latitude
}))
return [{
id: polylineId.value,
points,
color: '#007AFF',
width: 6,
dottedLine: false,
borderWidth: 1,
borderColor: '#0056b3'
}]
})
// 要显示在可视区域内的坐标点列表
const includePoints = computed(()=>{
const points = props.routePoints.map(point => ({
longitude: point.longitude,
latitude: point.latitude
}))
return points;
})
// 闭合多边形
const polygon = computed(()=>{
const points = props.routePoints.map(point => ({
longitude: point.longitude,
latitude: point.latitude
}))
return {
points,
strokeWidth:1,
strokeColor:'red',
fillColor:'lightgreen'
};
})
// 设置地图中心
const mapInstance = computed(() => {
// const mid = props.routePoints[Math.floor(props.routePoints.length / 2)];
const mid = props.routePoints[0];
return {
longitude: mid.longitude,
latitude: mid.latitude
}
})
// 缩放级别
const mapScale = ref(12);
const markerList = ref([])
const drawMap=()=>{
// nextTick(()=>{
// setTimeout(()=>{
// markerList.value = markers.value;
// mapContext.value.includePoints({
// points:includePoints.value,
// padding: [40, 40, 40, 40],
// success:(res)=>{
// console.log('success===>',res);
// },
// fail:(err)=>{
// console.log('fail===>',err);
// },
// complete:(res)=> {
// console.log('complete', res)
// }
// })
// },0)
// })
}
defineExpose({
drawMap
})
</script>
<style lang="scss" scoped>
.pMap {
overflow: hidden;
&-box {
width: 100%;
height: 500rpx;
&-callout{
position: relative;
&-list{
position: relative;
&-item{
position: relative;
display: inline-block;
border-radius: 6px;
background: rgba(255, 255, 255, 1);
padding: 8rpx 20rpx;
overflow: hidden;
&-center{
display: flex;
&-tag{
border-radius: 4px;
background: rgba(207, 19, 0, 0.4);
// width: 36rpx;
// height: 36rpx;
// line-height: 36rpx;
padding: 6rpx 10rpx;
// margin: 6rpx 10rpx;
color: rgba(207, 19, 0, 1);
font-size: 20rpx;
font-weight: 500;
overflow: hidden;
}
&-txt{
margin-left: 10rpx;
color: rgba(0, 0, 0, 1);
font-size: 24rpx;
font-weight: 400;
line-height: 28rpx;
}
}
}
}
}
}
}
</style> - 发布:29 分钟前
- 更新:29 分钟前
- 阅读:6
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: 版本 Windows 10 专业版 版本号 22H2 安装日期 2025/10/21 OS 内部版本 19045.6466
HBuilderX类型: 正式
HBuilderX版本号: 4.85
手机系统: Android
手机系统版本号: Android 16
手机厂商: 小米
手机机型: 863904075488527
页面类型: vue
vue版本: vue3
打包方式: 云端
项目创建方式: HBuilderX
示例代码:
操作步骤:
渲染器map组件绘制自定义气泡
渲染器map组件绘制自定义气泡
预期结果:
自定义气泡根据marker位置显示
自定义气泡根据marker位置显示
实际结果:
自定义气泡一直处于右上角显示
自定义气泡一直处于右上角显示
bug描述:
map marker 上的自定义气泡 customCallout显示气泡不对?
<template>
<view class="pMap">
<!-- -->
<map class="pMap-box"
id="mapContext"
:longitude="mapInstance.longitude"
:latitude="mapInstance.latitude"
:markers="markers"
:polyline="polyline"
:show-location="true"
:scale="mapScale"
:include-points="includePoints"
:polygon="polygon"
:style="{width:windowWidth+'px',height: '500rpx'}">
<cover-view class="pMap-box-callout" slot="callout">
<block v-for="(item,index) in markers" :key="index" >
<cover-view
v-if="item.customCallout"
class="pMap-box-callout-list"
:marker-id="item.id">
<cover-view class="pMap-box-callout-list-item">
<cover-view class="pMap-box-callout-list-item-center">
<cover-view class="pMap-box-callout-list-item-center-tag">
{{index == 0?'发':index == markers.length-1?'收':''}}
</cover-view>
<cover-view class="pMap-box-callout-list-item-center-txt">
{{item.title}}
</cover-view>
</cover-view>
</cover-view>
</cover-view>
</block>
</cover-view>
</map>
</view>
</template>
<script setup>
import startIcon from '@/static/image/order/map.png'
import processIcon from '@/static/image/order/car.png'
import {ref,getCurrentInstance,computed,defineExpose,onMounted, nextTick} from 'vue';
import {Config} from "@/http/config";
import {systemStore} from '@/store/system'
const {windowWidth} = systemStore();
const _this = getCurrentInstance();
const mapContext = ref(null);
onMounted(()=>{
mapContext.value = uni.createMapContext('mapContext',_this);
})
const props = defineProps({
routePoints: {
type: Array,
default: []
}
})
// 获取标记点图标
const getMarkerIconByStatus = (status) => {
switch (status) {
case 'start':
return startIcon;
case 'end':
return startIcon;
case 'process':
// return null;
return processIcon;
default:
return startIcon;
}
}
// 缓存节点颜色配置
const statusColorMap =(status)=> {
switch (status) {
case 'start':
return '#52c41a';
case 'end':
return '#52c41a';
case 'process':
return '#1890ff';
default:
return '#faad14';
}
};
// 构建标记点
const markers = computed( () => {
if (!props.routePoints || props.routePoints.length === 0) {
return []
}
return props.routePoints.map((marker, index) => {
// 根据状态设置标记点图标
let iconPath = getMarkerIconByStatus(marker.status);
let customCallout = undefined;
let width = '10px';
let height = '10px';
switch (marker.status) {
case 'start':
customCallout={
anchorY: 0,
anchorX: 0,
display:"ALWAYS",//一直展示
}
width = '28px';
height = '34px';
break;
case 'end':
customCallout ={
anchorY: 0,
anchorX: 0,
display:"ALWAYS",//一直展示
}
width = '28px';
height = '34px';
break;
case 'process':
width = '20px';
height = '15px';
break;
}
const markerId = `marker_${index}`;
// marker.id ||
return {
id: index || markerId,
longitude: marker.longitude,
latitude: marker.latitude,
title: marker.title,
iconPath,
width,
height,
customCallout,
joinCluster: true,
zIndex:1,
...marker
}
})
})
// 构建路线
const polylineId = ref('logistics-route');
const polyline = computed(() => {
if (!props.routePoints || props.routePoints.length < 2) {
return []
}
const points = props.routePoints.map(point => ({
longitude: point.longitude,
latitude: point.latitude
}))
return [{
id: polylineId.value,
points,
color: '#007AFF',
width: 6,
dottedLine: false,
borderWidth: 1,
borderColor: '#0056b3'
}]
})
// 要显示在可视区域内的坐标点列表
const includePoints = computed(()=>{
const points = props.routePoints.map(point => ({
longitude: point.longitude,
latitude: point.latitude
}))
return points;
})
// 闭合多边形
const polygon = computed(()=>{
const points = props.routePoints.map(point => ({
longitude: point.longitude,
latitude: point.latitude
}))
return {
points,
strokeWidth:1,
strokeColor:'red',
fillColor:'lightgreen'
};
})
// 设置地图中心
const mapInstance = computed(() => {
// const mid = props.routePoints[Math.floor(props.routePoints.length / 2)];
const mid = props.routePoints[0];
return {
longitude: mid.longitude,
latitude: mid.latitude
}
})
// 缩放级别
const mapScale = ref(12);
const markerList = ref([])
const drawMap=()=>{
// nextTick(()=>{
// setTimeout(()=>{
// markerList.value = markers.value;
// mapContext.value.includePoints({
// points:includePoints.value,
// padding: [40, 40, 40, 40],
// success:(res)=>{
// console.log('success===>',res);
// },
// fail:(err)=>{
// console.log('fail===>',err);
// },
// complete:(res)=> {
// console.log('complete', res)
// }
// })
// },0)
// })
}
defineExpose({
drawMap
})
</script>
<style lang="scss" scoped>
.pMap {
overflow: hidden;
&-box {
width: 100%;
height: 500rpx;
&-callout{
position: relative;
&-list{
position: relative;
&-item{
position: relative;
display: inline-block;
border-radius: 6px;
background: rgba(255, 255, 255, 1);
padding: 8rpx 20rpx;
overflow: hidden;
&-center{
display: flex;
&-tag{
border-radius: 4px;
background: rgba(207, 19, 0, 0.4);
// width: 36rpx;
// height: 36rpx;
// line-height: 36rpx;
padding: 6rpx 10rpx;
// margin: 6rpx 10rpx;
color: rgba(207, 19, 0, 1);
font-size: 20rpx;
font-weight: 500;
overflow: hidden;
}
&-txt{
margin-left: 10rpx;
color: rgba(0, 0, 0, 1);
font-size: 24rpx;
font-weight: 400;
line-height: 28rpx;
}
}
}
}
}
}
}
</style>
0 个回复