353 lines
7.6 KiB
Vue
353 lines
7.6 KiB
Vue
<template>
|
|
<view :style="{ width: '100%', height: height }">
|
|
<!-- 基础工具 -->
|
|
<view class="tool-location icon-style" @click="getLocation">
|
|
<uni-icons type="location" :size="toolIconSize"></uni-icons>
|
|
</view>
|
|
<!-- <view class="tool-refresh icon-style">
|
|
<uni-icons type="loop" :size="toolIconSize" @click="ajs"></uni-icons>
|
|
</view> -->
|
|
<view class="tool-top" v-show="isShowTab">
|
|
<view class="tab-wrapper">
|
|
<view
|
|
v-for="item in tabOption"
|
|
:key="item.value"
|
|
class="tab-item"
|
|
:style="{
|
|
borderColor: select.includes(item) ? '#3b80f8' : '#dcdcdc',
|
|
}"
|
|
@click="handleClickTab(item)"
|
|
>
|
|
<text :style="{ color: select.includes(item) ? '#3b80f8' : '' }">{{
|
|
item.label
|
|
}}</text>
|
|
<view class="tab-active-wrapper">
|
|
<uni-icons
|
|
v-show="select.includes(item)"
|
|
type="checkbox-filled"
|
|
size="16"
|
|
color="#3b80f8"
|
|
></uni-icons>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="coordinateType-wrapper">
|
|
<view
|
|
v-for="it of coordinateTypeOption"
|
|
:key="it.value"
|
|
:style="{
|
|
color: coordinateTypeSelect.includes(it) ? '#3b80f8' : '',
|
|
}"
|
|
@click="handleCoordinateType(it)"
|
|
>
|
|
{{ it.label }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 地图 -->
|
|
<map
|
|
id="mapRef"
|
|
ref="mapRef"
|
|
show-location
|
|
:style="{ width: '100%', height: height }"
|
|
:scale="scale"
|
|
:longitude="mapcenter.longitude"
|
|
:latitude="mapcenter.latitude"
|
|
:markers="markers"
|
|
:polygons="polygons"
|
|
:polyline="polylines"
|
|
@tap="ontap"
|
|
/>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, getCurrentInstance } from "vue";
|
|
import { findIndex } from "lodash";
|
|
import AMapWX from "@/utils/amap-wx.130.js";
|
|
import * as map from "@/utils/map.js";
|
|
|
|
let tab_list = [
|
|
{
|
|
label: "定位",
|
|
value: "location",
|
|
},
|
|
{
|
|
label: "扫码点",
|
|
value: "scan",
|
|
},
|
|
{
|
|
label: "还车点",
|
|
value: "return",
|
|
},
|
|
{
|
|
label: "轨迹",
|
|
value: "track",
|
|
},
|
|
{
|
|
label: "基站定位",
|
|
value: "base",
|
|
},
|
|
];
|
|
|
|
var amapsdk = new AMapWX({
|
|
key: map.sdkKey,
|
|
});
|
|
|
|
const { height, lng, lat, iconPath, toolIconSize, isShowTab, tabList } =
|
|
defineProps({
|
|
/*容器高度*/
|
|
height: {
|
|
type: String,
|
|
default: "100vh",
|
|
},
|
|
/*经度*/
|
|
lng: {
|
|
type: Number,
|
|
default: 116.397128,
|
|
},
|
|
/*纬度*/
|
|
lat: {
|
|
type: Number,
|
|
default: 39.916527,
|
|
},
|
|
/*工具图标大小*/
|
|
toolIconSize: {
|
|
type: [String, Number],
|
|
default: "28",
|
|
},
|
|
/*是否显示地图tab*/
|
|
isShowTab: {
|
|
type: Boolean,
|
|
default: false, // 是否显示地图tab
|
|
},
|
|
/*地图tab列表 TODO:未开发自定义tab选择后的事件*/
|
|
tabList: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
});
|
|
const emit = defineEmits(["change"]);
|
|
|
|
let mapContext = null;
|
|
const mapRef = ref("mapRef");
|
|
const mapcenter = ref({
|
|
longitude: null,
|
|
latitude: null,
|
|
});
|
|
const scale = ref(17);
|
|
const markers = ref([]);
|
|
const polylines = ref([]);
|
|
const polygons = ref([
|
|
// {
|
|
// points: [
|
|
// { longitude: 104.074085, latitude: 30.666171 },
|
|
// { longitude: 104.073085, latitude: 30.667171 },
|
|
// { longitude: 104.071085, latitude: 30.666171 },
|
|
// { longitude: 104.070085, latitude: 30.664171 },
|
|
// { longitude: 104.071085, latitude: 30.663171 },
|
|
// { longitude: 104.073085, latitude: 30.663171 },
|
|
// { longitude: 104.074085, latitude: 30.666171 },
|
|
// ],
|
|
// strokeWidth: 2,
|
|
// strokeColor: "#1791fc",
|
|
// fillColor: "#1791fc66",
|
|
// zIndex: 5,
|
|
// },
|
|
]);
|
|
|
|
const tabOption = tabList.length <= 0 ? ref(tab_list) : ref(tabList);
|
|
const coordinateTypeOption = ref([
|
|
{
|
|
label: "用户坐标",
|
|
value: "user",
|
|
},
|
|
{
|
|
label: "车辆坐标",
|
|
value: "vehicle",
|
|
},
|
|
]);
|
|
const select = ref([]);
|
|
const coordinateTypeSelect = ref([]);
|
|
|
|
const handleCoordinateType = (it) => {
|
|
const index = findIndex(coordinateTypeSelect.value, { value: it.value });
|
|
if (index === -1) {
|
|
coordinateTypeSelect.value.push(it);
|
|
} else {
|
|
coordinateTypeSelect.value.splice(index, 1);
|
|
}
|
|
};
|
|
|
|
const handleClickTab = (it) => {
|
|
const index = findIndex(select.value, { value: it.value });
|
|
if (index === -1) {
|
|
select.value.push(it);
|
|
} else {
|
|
select.value.splice(index, 1);
|
|
}
|
|
};
|
|
|
|
const getLocation = () => {
|
|
map.getLoalcation(mapContext, (res) => {
|
|
const { latitude, longitude } = res;
|
|
mapcenter.value = {
|
|
longitude: longitude,
|
|
latitude: latitude,
|
|
};
|
|
});
|
|
};
|
|
|
|
const ajs = () => {};
|
|
|
|
// 添加地图点位
|
|
const addMarker = (
|
|
marker,
|
|
options = {
|
|
isEmpty: true,
|
|
focus: true,
|
|
}
|
|
) => {
|
|
if (options.isEmpty) {
|
|
markers.value = [];
|
|
}
|
|
markers.value.push(
|
|
map.addMarker(
|
|
marker.id,
|
|
marker.longitude,
|
|
marker.latitude,
|
|
"bike-choose.png"
|
|
)
|
|
);
|
|
|
|
// 是否聚焦到新添加的点
|
|
if (options.focus) {
|
|
mapDirection(marker);
|
|
}
|
|
};
|
|
|
|
function mapDirection(marker) {
|
|
if (!marker || !marker.longitude || !marker.latitude) {
|
|
console.error("Invalid marker data");
|
|
return;
|
|
}
|
|
map.getLoalcation(mapContext, (res) => {
|
|
const { latitude: slat, longitude: slng } = res;
|
|
|
|
const options = {
|
|
mapsdk: amapsdk,
|
|
slng,
|
|
slat,
|
|
elng: marker.longitude,
|
|
elat: marker.latitude,
|
|
success: (res) => {
|
|
let { arrPoint, distance } = res;
|
|
|
|
mapContext.includePoints({
|
|
points: arrPoint,
|
|
padding: [50, 50, 50, 50], // 视野边缘与点的间距
|
|
success: () => {
|
|
polylines.value = [map.addLine("#1082FF", arrPoint)];
|
|
},
|
|
});
|
|
},
|
|
fail: (res) => {
|
|
console.log("fail", res);
|
|
},
|
|
};
|
|
|
|
map.direction(options);
|
|
});
|
|
}
|
|
|
|
onMounted(() => {
|
|
mapContext = uni.createMapContext("mapRef", getCurrentInstance());
|
|
// 初始化地图
|
|
if (mapContext) {
|
|
getLocation();
|
|
}
|
|
console.log("地图组件已加载", mapContext);
|
|
});
|
|
|
|
defineExpose({
|
|
addMarker,
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.icon-style {
|
|
position: absolute;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 100;
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
background-color: white;
|
|
border-radius: 50%;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
|
|
}
|
|
.tool-location {
|
|
left: 5%;
|
|
bottom: 15%;
|
|
}
|
|
.tool-refresh {
|
|
right: 5%;
|
|
bottom: 15%;
|
|
}
|
|
|
|
.tool-top {
|
|
position: absolute;
|
|
top: 20rpx;
|
|
left: 30rpx;
|
|
right: 30rpx;
|
|
padding: 20rpx;
|
|
background-color: white;
|
|
z-index: 100;
|
|
border-radius: 10rpx;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
|
|
|
|
.tab-wrapper {
|
|
width: 100%;
|
|
overflow-x: auto;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12rpx;
|
|
|
|
.tab-item {
|
|
position: relative;
|
|
flex-shrink: 0;
|
|
padding: 10rpx 35rpx;
|
|
border: 1px solid #dcdcdc;
|
|
border-radius: 10rpx;
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
white-space: nowrap;
|
|
|
|
.tab-active-wrapper {
|
|
position: absolute;
|
|
right: 8rpx;
|
|
bottom: 8rpx;
|
|
width: 20rpx;
|
|
height: 20rpx;
|
|
border-radius: 50%;
|
|
border: 1px solid #dcdcdc;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
}
|
|
}
|
|
|
|
.coordinateType-wrapper {
|
|
width: 100%;
|
|
overflow-x: auto;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 30rpx;
|
|
font-size: 26rpx;
|
|
margin-top: 25rpx;
|
|
}
|
|
}
|
|
</style>
|