init commit
43
src/App.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<vc-config-provider :cesium-path="CESIUM_PATH">
|
||||
<Earth>
|
||||
<LocatingPoint />
|
||||
<MarkPoints />
|
||||
</Earth>
|
||||
</vc-config-provider>
|
||||
|
||||
<LonlatForm id="lonlat-form"></LonlatForm>
|
||||
<LonlatTable id="lonlat-table"></LonlatTable>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { VcConfigProvider } from 'vue-cesium'
|
||||
import Earth from '/@/components/Earth.vue'
|
||||
import LonlatForm from '/@/components/LonlatForm.vue'
|
||||
import LonlatTable from '/@/components/LonlatTable.vue'
|
||||
import MarkPoints from "/@/components/MarkPoints.vue";
|
||||
import LocatingPoint from '/@/components/LocatingPoint.vue'
|
||||
|
||||
const CESIUM_PATH = (process.env.NODE_ENV === 'development' ? './node_modules/cesium/Build/Cesium/Cesium.js': './Cesium/Cesium.js')
|
||||
</script>
|
||||
|
||||
<style>
|
||||
html, body, #app {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#lonlat-form {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
#lonlat-table {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 15px;
|
||||
}
|
||||
</style>
|
||||
BIN
src/assets/logo.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
src/assets/pin.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/assets/poi/1.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/assets/poi/10.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/poi/2.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/poi/3.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/poi/4.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/poi/5.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/poi/6.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/poi/7.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/poi/8.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/poi/9.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
12
src/assets/poi/index.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import poi1 from '/@/assets/poi/1.png'
|
||||
import poi2 from '/@/assets/poi/2.png'
|
||||
import poi3 from '/@/assets/poi/3.png'
|
||||
import poi4 from '/@/assets/poi/4.png'
|
||||
import poi5 from '/@/assets/poi/5.png'
|
||||
import poi6 from '/@/assets/poi/6.png'
|
||||
import poi7 from '/@/assets/poi/7.png'
|
||||
import poi8 from '/@/assets/poi/8.png'
|
||||
import poi9 from '/@/assets/poi/9.png'
|
||||
import poi10 from '/@/assets/poi/10.png'
|
||||
|
||||
export default [ poi1, poi2, poi3, poi4, poi5, poi6, poi7, poi8, poi9, poi10 ]
|
||||
69
src/components/Earth.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<vc-viewer
|
||||
:showCredit="false"
|
||||
@ready="ready"
|
||||
@leftDoubleClick="leftDoubleClick">
|
||||
|
||||
<vc-layer-imagery>
|
||||
<vc-imagery-provider-urltemplate
|
||||
:projectionTransforms="projectionTransforms"
|
||||
:url="img_url"
|
||||
></vc-imagery-provider-urltemplate>
|
||||
</vc-layer-imagery>
|
||||
|
||||
<vc-layer-imagery>
|
||||
<vc-imagery-provider-urltemplate
|
||||
:projectionTransforms="projectionTransforms"
|
||||
:url="ann_url"
|
||||
></vc-imagery-provider-urltemplate>
|
||||
</vc-layer-imagery>
|
||||
|
||||
<vc-status-bar />
|
||||
|
||||
<slot></slot>
|
||||
</vc-viewer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { usePointStore } from '/@/stores/point'
|
||||
import { VcViewer, VcStatusBar, VcLayerImagery, VcImageryProviderUrltemplate } from 'vue-cesium'
|
||||
|
||||
const projectionTransforms = { from : 'GCJ02', to : 'WGS84' }
|
||||
|
||||
const img_url = 'https://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&style=6'
|
||||
const ann_url = 'https://webst01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&style=8'
|
||||
|
||||
let Cesium = null, viewer = null
|
||||
const ready = readyObj => {
|
||||
Cesium = readyObj.Cesium
|
||||
viewer = readyObj.viewer
|
||||
}
|
||||
|
||||
const point = usePointStore()
|
||||
const leftDoubleClick = ({ position }) => {
|
||||
if (!viewer) return
|
||||
|
||||
if (point.index >= point.length) {
|
||||
alert(`最多只能够添加 ${ point.length } 个点`);
|
||||
return
|
||||
}
|
||||
|
||||
const cartesian = viewer.camera.pickEllipsoid(position, viewer.scene.globe.ellipsoid)
|
||||
|
||||
if (!cartesian) return
|
||||
|
||||
const lnglat = cartesian2Lonlat(cartesian)
|
||||
|
||||
point.addItem( lnglat )
|
||||
}
|
||||
|
||||
const cartesian2Lonlat = cartesian => {
|
||||
if ( !Cesium ) return
|
||||
|
||||
const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
|
||||
const lng = Cesium.Math.toDegrees(cartographic.longitude).toFixed(8);
|
||||
const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(8);
|
||||
|
||||
return { lng, lat }
|
||||
}
|
||||
</script>
|
||||
7
src/components/LocatingPoint.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<Pin :position="{ lng: 116.4, lat: 39.9 }" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Pin from '/@/components/Pin.vue'
|
||||
</script>
|
||||
65
src/components/LonlatForm.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<form>
|
||||
<label>经度:</label>
|
||||
<input type="text" id="lon-input" placeholder="请输入经度值">
|
||||
<label>纬度:</label>
|
||||
<input type="text" id="lat-input" placeholder="请输入纬度值">
|
||||
<input type="button" id="fly-btn" @click="onFlyBtnClick" value="飞到这个点">
|
||||
<input type="button" id="clear-btn" @click="onClearBtnClick" value="清除坐标">
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { usePointStore } from '../stores/point'
|
||||
|
||||
const onFlyBtnClick = () => {
|
||||
|
||||
}
|
||||
|
||||
|
||||
const point = usePointStore()
|
||||
const onClearBtnClick = () => {
|
||||
point.$reset()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
form {
|
||||
background-color: #303336;
|
||||
border: 1px solid #ea4;
|
||||
color: #edffff;
|
||||
fill: #edffff;
|
||||
border-radius: 4px;
|
||||
padding: 5px 12px;
|
||||
margin: 2px 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
label {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 5px 10px;
|
||||
padding: 5px 10px;
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input#fly-btn, input#clear-btn {
|
||||
border-radius: 3px;
|
||||
background-color: #41ddee;
|
||||
}
|
||||
|
||||
input#fly-btn:hover , input#clear-btn:hover {
|
||||
background-color: #ffffff;
|
||||
color: #41ddee;
|
||||
}
|
||||
|
||||
</style>
|
||||
61
src/components/LonlatTable.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<table v-if="show">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>经度</th>
|
||||
<th>纬度</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="point-list">
|
||||
<tr v-for="item, index in point.items" :key="index">
|
||||
<td>{{ index + 1 }}</td>
|
||||
<td>{{ item ? item.lng : ''}}</td>
|
||||
<td>{{ item ? item.lat : ''}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { usePointStore } from '../stores/point'
|
||||
|
||||
const point = usePointStore()
|
||||
const show = computed(() => point.index)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
table {
|
||||
color: #FFFFFF;
|
||||
background-color: #242424;
|
||||
padding: 10px;
|
||||
border-radius: 7px;
|
||||
border-collapse: separate;
|
||||
border-spacing: 2px;
|
||||
}
|
||||
|
||||
table th:first-child {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
table th:not(:first-child) {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
table thead tr {
|
||||
background-color: rgba(84, 84, 84, 0.8);
|
||||
}
|
||||
|
||||
table tbody tr:nth-child(even) {
|
||||
background-color: rgba(84, 84, 84, 0.8);
|
||||
}
|
||||
|
||||
table tbody tr:nth-child(odd) {
|
||||
background-color: rgba(84, 84, 84, 0.25);
|
||||
}
|
||||
|
||||
table th, table td {
|
||||
padding: 3px 5px;
|
||||
}
|
||||
</style>
|
||||
15
src/components/MarkPoints.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<Pin
|
||||
v-for="item, index in point.items"
|
||||
:key="index"
|
||||
:position="item"
|
||||
:image="pois[index]"/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { usePointStore } from '/@/stores/point'
|
||||
import Pin from '/@/components/Pin.vue'
|
||||
import pois from '/@/assets/poi'
|
||||
|
||||
const point = usePointStore()
|
||||
</script>
|
||||
32
src/components/Pin.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<vc-entity :show="show" :position="position">
|
||||
<vc-graphics-billboard :image="image" :verticalOrigin="1" />
|
||||
</vc-entity>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { VcEntity, VcGraphicsBillboard } from 'vue-cesium'
|
||||
|
||||
import { computed } from 'vue'
|
||||
import pin from '/@/assets/pin.png'
|
||||
|
||||
const props = defineProps({
|
||||
position: {
|
||||
type: Object,
|
||||
default: { lng: NaN, lat: NaN },
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
default: pin,
|
||||
}
|
||||
})
|
||||
|
||||
const show = computed(() => {
|
||||
const { lng, lat } = props.position
|
||||
|
||||
if (isNaN(lng) || lng > 180 || lng < -180) return false
|
||||
if (isNaN(lat) || lat > 90 || lat < -90 ) return false
|
||||
|
||||
return true
|
||||
})
|
||||
</script>
|
||||
7
src/main.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createPinia } from 'pinia'
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
import 'vue-cesium/dist/index.css';
|
||||
|
||||
createApp(App).use(createPinia()).mount('#app')
|
||||
28
src/stores/Point.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
|
||||
export const usePointStore = defineStore({
|
||||
id: 'point',
|
||||
state: () => ({
|
||||
index: 0,
|
||||
length: 10,
|
||||
rawItems: [],
|
||||
}),
|
||||
getters: {
|
||||
items: (state) => {
|
||||
const items = state.rawItems
|
||||
items.length = state.length
|
||||
|
||||
return items
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
addItem(item) {
|
||||
if (this.index >= this.length) {
|
||||
return
|
||||
}
|
||||
this.rawItems[this.index] = item
|
||||
this.index++
|
||||
},
|
||||
},
|
||||
})
|
||||