提交 7837ae82 编写于 作者: W weixin_46115723

Tue Apr 23 10:19:00 CST 2024 inscode

上级 bb82d06b
......@@ -4,6 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://api.tianditu.gov.cn/api?v=4.0&tk=7ed13693ab1597b0099d415636165772" async type="text/javascript"></script>
<title>Vite App</title>
</head>
<body>
......
......@@ -4,82 +4,11 @@ import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<header>
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />
<div class="wrapper">
<HelloWorld msg="You did it!" />
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
</div>
</header>
<RouterView />
</template>
<style scoped>
header {
line-height: 1.5;
max-height: 100vh;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
nav {
width: 100%;
font-size: 12px;
text-align: center;
margin-top: 2rem;
}
nav a.router-link-exact-active {
color: var(--color-text);
}
nav a.router-link-exact-active:hover {
background-color: transparent;
}
nav a {
display: inline-block;
padding: 0 1rem;
border-left: 1px solid var(--color-border);
}
nav a:first-of-type {
border: 0;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
nav {
text-align: left;
margin-left: -1rem;
font-size: 1rem;
padding: 1rem 0;
margin-top: 1rem;
}
#main {
height: 100vh;
}
</style>
@import "./base.css";
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
vertical-align: baseline;
text-decoration: none;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
font-weight: normal;
ol, ul {
list-style: none;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
blockquote, q {
quotes: none;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
a {
color: var(--el-color-primary);
}
/*scroll*/
/*定义滚动条宽高及背景,宽高分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar {
width: 8px;
height: 8px;
background-color: transparent;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
body {
overflow-x: hidden;
}
::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2);
border-radius: 5px;
transition: background-color ease 1s;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(0, 0, 0, 1);
}
/*定义滚动条的轨道,内阴影及圆角*/
::-webkit-scrollbar-track {
background-color: transparent;
}
#app {
height: 100vh;
width: 100vw;
}
......@@ -7,15 +7,7 @@ const router = createRouter({
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue')
component: () => import('../views/TMap/index.vue')
}
]
})
......
<template>
<div class="infowindowClass">
<div class="windows_close" @click="close"></div>
<div class="_head">信息窗口自定义</div>
<div class="_body">
{{ data }}
</div>
<div class="_foot">
<el-button type="primary" @click="callback">确定</el-button>
</div>
</div>
</template>
<script>
export default {
props: {
// 传递数据对象
data: {
type: Object,
default: () => {},
},
// 信息窗口对象
infoWindow: {
type: Object,
default: () => {},
},
},
methods: {
// 关闭
close() {
this.infoWindow.closeInfoWindow()
},
// 确认回调
callback() {
this.$emit('callback', this.data)
},
},
}
</script>
<style lang="scss">
// $color: red;
$color: rgba(255, 255, 255, 1);
// 信息窗口隐藏源码样式
.tdt-infowindow-content-wrapper,
.tdt-infowindow-tiptdt-infowindow-content-wrapper {
color: unset;
background: transparent;
box-shadow: unset;
}
.tdt-infowindow-content {
margin: 0;
}
.tdt-infowindow-tip-container {
display: none;
}
// 信息窗口隐藏源码样式 - end
.infowindowClass {
position: relative;
// position: absolute;
// top: 0;
// left: 0;
display: flex;
flex-direction: column;
width: 300px;
height: 150px;
padding: 10px;
background-color: $color;
border-radius: 10px;
// zhtips: 三角形
&::before {
position: absolute;
bottom: -9px;
left: 50%;
width: 0;
height: 0;
content: '';
border-color: $color transparent transparent transparent;
border-style: solid;
border-width: 10px 10px 0 10px;
transform: translate(-50%, 0);
}
._head {
padding-bottom: 10px;
}
._body {
flex: 1;
}
._foot {
display: flex;
align-items: center;
justify-content: center;
}
}
//zhtips: 窗口右上角关闭按钮X
$closeColor: #333;
.windows_close {
position: absolute;
top: 0;
right: 0;
width: 30px;
height: 30px;
transform: rotate(45deg);
&::before {
position: absolute;
top: 50%;
left: 50%;
display: block;
width: 10px;
height: 1px;
content: '';
background-color: $closeColor;
transform: translate3d(-50%, -50%, 0);
}
&::after {
position: absolute;
top: 50%;
left: 50%;
display: block;
width: 1px;
height: 10px;
content: '';
background-color: $closeColor;
transform: translate3d(-50%, -50%, 0);
}
}
</style>
<script setup>
// import menuEdit from '@adm/base/menu/edit.vue';
import { onMounted, reactive, ref, computed, watch, nextTick } from 'vue';
// import useModalMinix from '@/hook/modal.js';
// import { useUserStore } from "@/stores/user.js";
// import { getList } from "@/api/api.js";
// import { post } from '@/function/request/index.js'
defineOptions({name: ''});
// const {baseDataMap, formRef, form, saveForm, loading, submitLoading, closeModal} = useModalMinix();
// const { baseURL } = useUserStore();
const props = defineProps({})
const emits = defineEmits(['on-ok']);
// watch(() => foo, (newValue, oldValue) => {})
const demoLnglat = ref('120.209809, 30.246587') //模拟经纬度
// 模拟点阵数组
const demoPath = ref([
[120.13292, 30.2624],
[120.16339, 30.25492],
[120.16159, 30.23089],
[120.13181, 30.23252],
])
const mapConfig = reactive({
map: null, //地图容器
zoom: 10, //缩放等级
center: [120.209809, 30.246587], //默认中心点
contextMenu: null, //右键菜单
marker: null, //点
markers: null, //多个点
markerCluster: null, //点聚合
line: null, //线
polygon: null, //面
infoWindow: null, //信息窗口
infoWindowData: {}, //信息窗口数据
})
const showInfoWindow = ref(false) //信息窗口显示
// 初始化地图
const initMap = () => {
const imageURL1 = 'http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=7ed13693ab1597b0099d415636165772';
const imageURL2 = 'http://t0.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=7ed13693ab1597b0099d415636165772';
const lay1 = new T.TileLayer(imageURL1, {minZoom: 1, maxZoom: 18});
const lay2 = new T.TileLayer(imageURL2, {minZoom: 1, maxZoom: 18});
mapConfig.map = new T.Map('mapID', {layers: [lay1, lay2]})
mapConfig.map.centerAndZoom(
returnLnglat(mapConfig.center),
mapConfig.zoom
)
initMapAfter() //加载地图后方法
}
//初始化地图后操作
const initMapAfter = () => {
//todo do something
}
// 添加单个点标记
const addMarker = (lnglat) => {
clearMap() //清除覆盖物
// 自定义标记点图标
let markerObj = {
icon: new T.Icon({
iconUrl: 'http://api.tianditu.gov.cn/img/map/markerA.png',
iconSize: new T.Point(30, 40),
iconAnchor: new T.Point(15, 40),
}),
}
mapConfig.marker = new T.Marker(
returnLnglat(lnglat)
// markerObj
)
// 添加标记点右键单击事件
mapConfig.marker.addEventListener('contextmenu', (event) => {
console.log('添加标记点右键单击事件', event)
//todo do something
})
mapConfig.map.addOverLay(mapConfig.marker)
reset('marker') //自适应画面
//点标记添加点击事件并传参
addClickHandler(mapConfig.marker, {
lnglat: lnglat,
})
}
// 添加点击事件返回
const addClickHandler = (marker, params, index) => {
marker.addEventListener('click', (e) => {
mapConfig.map.panTo(returnLnglat(e.lnglat), 12) //将地图的中心点变换到指定的地理坐标
markerClick(e, params, index)
})
}
// 点击时间打开信息窗体
const markerClick = (e, params, index) => {
console.log(e, params, index)
showInfoWindow.value = true //显示信息窗体
mapConfig.infoWindowData = params //传递数据
// 创建信息窗口对象
mapConfig.infoWindow = new T.InfoWindow(
this.$refs['infoWindow'].$el,
{ offset: new T.Point(0, -20), closeButton: false }
)
setTimeout(() => {
mapConfig.map.openInfoWindow(mapConfig.infoWindow, e.lnglat) //打开信息窗口
}, 0)
}
// 信息窗口点击回调
const infoWindowCallback = (data) => {
console.log('信息窗口点击回调', data)
//todo do something
this.closeInfoWindow() // 关闭信息弹窗
}
// 关闭信息弹窗
const closeInfoWindow = () => {
if (mapConfig.infoWindow) {
mapConfig.infoWindow.closeInfoWindow()
}
}
// 添加多个点标记
const addMarkers = (path) => {
clearMap() //清除覆盖物
let tempMarkers = []
let infoWindows = []
path.forEach((element) => {
let tempMarker = new T.Marker(returnLnglat(element))
mapConfig.map.addOverLay(tempMarker)
tempMarkers.push(tempMarker)
// let infoWindow = new T.InfoWindow();
// infoWindow.setLngLat(element);
// infoWindow.setContent(
// '<div style="color: #000;text-align: left;font-size: 18px;">' +
// '<p style="">' + '信息窗口' + '</p>' +
// '</div>'
// );
// infoWindows.push(infoWindow);
// tempMarker.addEventListener("mouseover", function () {
// tempMarker.openInfoWindow(infoWindow);
// });
// tempMarker.addEventListener("mouseout", function () {
// tempMarker.closeInfoWindow();
// });
})
mapConfig.markers = tempMarkers
// mapConfig.infoWindow = infoWindows
reset('markers') //自适应画面
}
// 添加点聚合
const addMarkerCluster = () => {
clearMap('markerCluster') //清除覆盖物
let tempMarkerCluster = []
for (var i = 0; i < 100; i++) {
// 定义浙江省的大致经纬度范围
var minLng = 118.018 // 最小经度
var maxLng = 123.7088 // 最大经度
var minLat = 27.0973 // 最小纬度
var maxLat = 31.0493 // 最大纬度
// 随机生成浙江省范围内的经度和纬度
var randomLng = Math.random() * (maxLng - minLng) + minLng
var randomLat = Math.random() * (maxLat - minLat) + minLat
var marker = new T.Marker(returnLnglat([randomLng, randomLat]), {
title: i,
})
console.log('marker', marker);
tempMarkerCluster.push(marker)
}
console.log('tempMarkerCluster', tempMarkerCluster);
mapConfig.markerCluster = new T.MarkerClusterer(
mapConfig.map,
{ markers: tempMarkerCluster }
)
reset('markerCluster') //自适应画面
}
// 添加单个线条
const addLine = (path) => {
clearMap() //清除覆盖物
const tempPath = []
path.forEach((element) => {
tempPath.push(returnLnglat(element))
})
mapConfig.line = new T.Polyline(tempPath)
mapConfig.map.addOverLay(mapConfig.line)
reset('line') //自适应画面
}
// 添加单个多边形覆盖物
const addPolygon = (path) => {
clearMap() //清除覆盖物
const tempPath = []
path.forEach((element) => {
tempPath.push(returnLnglat(element))
})
mapConfig.polygon = new T.Polygon(tempPath)
// 添加右键单击事件
mapConfig.polygon.addEventListener('contextmenu', (event) => {
addRightMenu(event)
})
mapConfig.map.addOverLay(mapConfig.polygon)
reset('polygon') //自适应画面
}
// 创建右键菜单
const addRightMenu = (e) => {
console.log('addRightMenu', e)
if (mapConfig.contextMenu) clearRightMenu() //清除右键菜单
mapConfig.contextMenu = document.createElement('div')
mapConfig.contextMenu.id = 'contextMenu'
mapConfig.contextMenu.innerHTML = `<div class='menu-item' id='edit'>编辑</div>
<div class='menu-item' id='del'>删除</div>`
// 设置菜单位置
mapConfig.contextMenu.style.left = e.layerPoint.x + 'px'
mapConfig.contextMenu.style.top = e.layerPoint.y + 'px'
mapConfig.map
.getContainer()
.appendChild(mapConfig.contextMenu) // 将菜单添加到地图容器中
document.getElementById('edit').addEventListener('click', () => {
console.log('编辑')
clearRightMenu() //清除右键菜单
})
document.getElementById('del').addEventListener('click', () => {
console.log('删除')
clearRightMenu() //清除右键菜单
})
// 监听地图的点击事件 隐藏右键菜单
mapConfig.map.addEventListener('click', () => {
clearRightMenu() //清除右键菜单
})
}
// 清除右键菜单
const clearRightMenu = () => {
var contextMenu = document.querySelector('#contextMenu')
if (contextMenu) {
mapConfig.map.getContainer().removeChild(contextMenu)
}
mapConfig.contextMenu = null
}
// 图层切换
const changeLayer = (type) => {
let layerType = null
switch (type) {
case 'BZ': //标准
layerType = window.TMAP_NORMAL_MAP
break
case 'WX': //卫星
layerType = window.TMAP_SATELLITE_MAP
break
case 'WXLW': //卫星路网
layerType = window.TMAP_HYBRID_MAP
break
case 'DX': //地形
layerType = window.TMAP_TERRAIN_MAP
break
case 'DXLW': //地形路网
layerType = window.TMAP_TERRAIN_HYBRID_MAP
break
default:
break
}
mapConfig.map.setMapType(layerType)
}
// 清除地图
const clearMap = (type) => {
switch (type) {
case 'marker':
if (mapConfig.marker) {
mapConfig.map.removeOverLay(mapConfig.marker) //移除覆盖物到地图上
mapConfig.marker = null
}
break
case 'line':
if (mapConfig.line) {
mapConfig.map.removeOverLay(mapConfig.line) //移除覆盖物到地图上
mapConfig.line = null
}
break
case 'markers':
if (mapConfig.markers) {
mapConfig.markers.forEach((item) => {
mapConfig.map.removeOverLay(item) //移除覆盖物到地图上
})
mapConfig.markers = null
}
break
case 'circleMarker':
if (mapConfig.circleMarker) {
mapConfig.map.removeOverLay(mapConfig.circleMarker)
mapConfig.circleMarker = null
}
break
default:
mapConfig.map.clearOverLays()
// 清除所有聚合点标记
if (mapConfig.markerCluster) {
mapConfig.markerCluster.clearMarkers() //移除覆盖物到地图上
mapConfig.markerCluster = null
}
// 清除信息窗口
if (mapConfig.infoWindow) {
mapConfig.infoWindow.closeInfoWindow()
}
break
}
}
// 自适应标记覆盖物到合适范围
const reset = (drawType) => {
let mapData = ''
switch (drawType) {
case 'marker':
mapData = [mapConfig.marker.getLngLat()]
break
case 'markers':
let tempMakerArr = []
mapConfig.markers.forEach((element) => {
tempMakerArr.push(returnLnglat(element.or))
})
mapData = tempMakerArr
break
case 'markerCluster':
// 获取所有标记点的经度和纬度坐标
var allLng = 0
var allLat = 0
const tempMarkerClusterArr = mapConfig.map.getOverlays()
tempMarkerClusterArr.forEach((element) => {
allLng += element.or.lng
allLat += element.or.lat
})
// 计算中心点的经纬度坐标
var centerLng = allLng / tempMarkerClusterArr.length
var centerLat = allLat / tempMarkerClusterArr.length
// 这里模拟计算有误差 一般固定写某个经纬度和层级
mapConfig.map.centerAndZoom(
returnLnglat([centerLng, centerLat]),
7
)
break
case 'line':
mapData = mapConfig.line.getLngLats()
break
case 'polygon':
mapData = mapConfig.polygon.getLngLats()[0] //获取覆盖物点阵数组
break
default:
break
}
mapConfig.map.setViewport(mapData) //适应范围
}
// 返回天地图经纬度对象
const returnLnglat = (data) => {
let x,
y = null
switch (typeof data) {
case 'string':
let lnglat = data.split(',')
x = lnglat[0]
y = lnglat[1]
break
case 'object':
if (data && data.lng) {
x = data.lng
y = data.lat
} else {
x = data[0]
y = data[1]
}
break
default:
break
}
return new T.LngLat(x, y)
}
onMounted(() => {
initMap() //初始化地图
});
// 子组件暴露
defineExpose({});
</script>
<template>
<div style="height: 100%;width: 100%;">
<div class="tool_container">
<button class="_btn" type="button" @click="addMarker(demoLnglat)">
添加点
</button>
<button class="_btn" type="button" @click="addMarkers(demoPath)">
添加多个点
</button>
<button class="_btn" type="button" @click="addMarkerCluster()">
添加点聚合
</button>
<button class="_btn" type="button" @click="addLine(demoPath)">
添加线
</button>
<button class="_btn" type="button" @click="addPolygon(demoPath)">
添加面
</button>
<button class="_btn" type="button" @click="changeLayer('BZ')">
切换标准图层
</button>
<button class="_btn" type="button" @click="changeLayer('WX')">
切换卫星图层
</button>
<button class="_btn" type="button" @click="changeLayer('WXLW')">
切换卫星路网图层
</button>
<button class="_btn" type="button" @click="changeLayer('DX')">
切换地形图层
</button>
<button class="_btn" type="button" @click="changeLayer('DXLW')">
切换地形路网图层
</button>
<button class="_btn" type="button" @click="clearMap()">清空所有</button>
</div>
<!--Tips 这个 @contextmenu.prevent 是阻止浏览器上地图默认的右键事件 -->
<div @contextmenu.prevent id="mapID" class="map_container" style="height: 100%;width: 100%;"></div>
<!-- <InfoWindow
ref="infoWindow"
v-show="showInfoWindow"
:infoWindow="mapConfig.infoWindow"
:data="mapConfig.infoWindowData"
@callback="infoWindowCallback"
></InfoWindow> -->
</div>
</template>
<style lang="less" scoped>
</style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册