192 lines
5.7 KiB
HTML
192 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||
<title>坐标定位</title>
|
||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
|
||
<style>
|
||
* { margin:0; padding:0; box-sizing:border-box; }
|
||
body { font-family:"Microsoft YaHei",Arial,sans-serif; height:100vh; display:flex; overflow:hidden; }
|
||
#app { display:flex; width:100%; height:100vh; }
|
||
|
||
#mapWrap { flex:1; position:relative; min-width:0; height:100%; }
|
||
#map { height:100%; width:100%; }
|
||
|
||
#sidePanel {
|
||
width:320px; height:100vh; background:#fff;
|
||
border-left:1px solid #e0e0e0;
|
||
display:flex; flex-direction:column; flex-shrink:0;
|
||
position:relative; z-index:10000;
|
||
box-shadow:-2px 0 12px rgba(0,0,0,0.08);
|
||
}
|
||
|
||
.panel-section {
|
||
padding:16px; border-bottom:2px solid #eee; flex-shrink:0;
|
||
}
|
||
.panel-section .title {
|
||
font-size:14px; font-weight:bold; color:#333; margin-bottom:12px;
|
||
}
|
||
|
||
.input-group {
|
||
margin-bottom:10px;
|
||
}
|
||
.input-group label {
|
||
display:block; font-size:12px; color:#888; margin-bottom:4px;
|
||
}
|
||
.input-group input {
|
||
width:100%; padding:10px 12px; border:1px solid #ddd; border-radius:6px;
|
||
font-size:14px; background:#fff;
|
||
}
|
||
.input-group input:focus {
|
||
outline:none; border-color:#27ae60; box-shadow:0 0 0 2px rgba(39,174,96,0.1);
|
||
}
|
||
|
||
.btn {
|
||
width:100%; padding:10px 0; border:none; border-radius:6px;
|
||
cursor:pointer; font-size:14px; font-weight:bold; transition:all 0.2s;
|
||
}
|
||
.btn-primary { background:#27ae60; color:#fff; }
|
||
.btn-primary:hover { background:#219653; }
|
||
|
||
.tip-box {
|
||
padding:10px 12px; background:#f0fff0; border:1px solid #d4edda;
|
||
border-radius:6px; font-size:12px; color:#27ae60; margin-top:12px;
|
||
}
|
||
.tip-box b { color:#333; }
|
||
|
||
.custom-marker-icon { background:none !important; border:none !important; }
|
||
|
||
@media (max-width:768px) {
|
||
#app { display:block; position:relative; }
|
||
#mapWrap { width:100%; height:55%; }
|
||
#sidePanel {
|
||
position:absolute; bottom:0; left:0;
|
||
width:100%; height:45%;
|
||
border-left:none; border-top:1px solid #e0e0e0;
|
||
border-radius:12px 12px 0 0;
|
||
box-shadow:0 -2px 12px rgba(0,0,0,0.08);
|
||
}
|
||
.input-group input { min-height:44px; font-size:15px; }
|
||
.btn { min-height:44px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="app">
|
||
<div id="mapWrap"><div id="map"></div></div>
|
||
|
||
<div id="sidePanel">
|
||
<div class="panel-section">
|
||
<div class="title">坐标定位</div>
|
||
<div class="input-group">
|
||
<label>纬度 (纬度在前)</label>
|
||
<input type="text" v-model="lat" placeholder="如:30.2856" @keyup.enter="locateByCoord" class="lat-tag">
|
||
</div>
|
||
<div class="input-group">
|
||
<label>经度 (经度在后)</label>
|
||
<input type="text" v-model="lng" placeholder="如:109.4783" @keyup.enter="locateByCoord" class="lng-tag">
|
||
</div>
|
||
<button class="btn btn-primary" @click="locateByCoord">定位到此坐标</button>
|
||
</div>
|
||
|
||
<div class="panel-section" v-if="lat && lng">
|
||
<div class="title">当前坐标</div>
|
||
<div class="tip-box">
|
||
纬度:<b>{{lat}}</b><br>
|
||
经度:<b>{{lng}}</b>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||
<script>
|
||
new Vue({
|
||
el: "#app",
|
||
data: {
|
||
map: null,
|
||
markerGroup: null,
|
||
markerIcon: null,
|
||
activeMarker: null,
|
||
lat: '',
|
||
lng: ''
|
||
},
|
||
mounted() {
|
||
this.initMap();
|
||
// 从URL参数读取初始坐标
|
||
var params = new URLSearchParams(window.location.search);
|
||
var initLat = parseFloat(params.get('lat'));
|
||
var initLng = parseFloat(params.get('lng'));
|
||
if (!isNaN(initLat) && !isNaN(initLng)) {
|
||
this.lat = initLat + '';
|
||
this.lng = initLng + '';
|
||
this.locateByCoord();
|
||
}
|
||
},
|
||
methods: {
|
||
initMap() {
|
||
this.map = L.map('map').setView([30.2856, 109.4783], 13);
|
||
L.tileLayer('http://localhost:3080/seeyon/seeyonExtend/assetsMap/map/{z}/{x}/{y}/tile.png', { maxZoom: 18, minZoom: 8 }).addTo(this.map);
|
||
var self = this;
|
||
setTimeout(function() { self.map.invalidateSize(); }, 100);
|
||
|
||
this.markerIcon = L.divIcon({
|
||
html: '<img src="./markicon.png" style="width:48px;height:48px;">',
|
||
className: 'custom-marker-icon',
|
||
iconSize: [48, 48],
|
||
iconAnchor: [24, 24]
|
||
});
|
||
this.markerGroup = L.layerGroup().addTo(this.map);
|
||
|
||
// 点击地图:放大到18级,回写经纬度
|
||
this.map.on('click', function(e) {
|
||
var clickLat = parseFloat(e.latlng.lat.toFixed(6));
|
||
var clickLng = parseFloat(e.latlng.lng.toFixed(6));
|
||
self.lat = clickLat + '';
|
||
self.lng = clickLng + '';
|
||
self.placeMarker(clickLat, clickLng);
|
||
self.map.setView([clickLat, clickLng], 18);
|
||
});
|
||
},
|
||
|
||
// 输入坐标定位
|
||
locateByCoord() {
|
||
var lat = parseFloat(this.lat);
|
||
var lng = parseFloat(this.lng);
|
||
if (isNaN(lat) || isNaN(lng)) {
|
||
alert('请输入有效的经纬度');
|
||
return;
|
||
}
|
||
this.placeMarker(lat, lng);
|
||
this.map.setView([lat, lng], 18);
|
||
},
|
||
|
||
// 在地图上放置标记
|
||
placeMarker(lat, lng) {
|
||
this.markerGroup.clearLayers();
|
||
var self = this;
|
||
var m = L.marker([lat, lng], { icon: this.markerIcon });
|
||
m.bindPopup(
|
||
'纬度:<b>' + lat + '</b><br>经度:<b>' + lng + '</b>',
|
||
{ offset: [0, -24] }
|
||
);
|
||
m.addTo(this.markerGroup);
|
||
self.activeMarker = m;
|
||
setTimeout(function() { m.openPopup(); }, 200);
|
||
}
|
||
}
|
||
});
|
||
|
||
function OK() {
|
||
var latlng = '';
|
||
const latText = $('.lat-tag').val();
|
||
const lngText = $('.lng-tag').val();
|
||
latlng = latText + "," +lngText
|
||
return latlng;
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|