AI 生成: 一个面向个人/团队/家庭的智能旅游规划工具,支持AI行程生成、地图标注与景点打卡记录。
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
// 地图与景点标注逻辑
|
||||
(function () {
|
||||
// 初始化地图:默认定位到中国杭州
|
||||
const map = L.map('map').setView([30.2741, 120.1551], 11);
|
||||
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
attribution: '© OpenStreetMap'
|
||||
}).addTo(map);
|
||||
|
||||
// 保存所有标注:{ id, name, lat, lng, status: 'visited' | 'wish' }
|
||||
let spots = [];
|
||||
const markers = {}; // id -> L.Marker
|
||||
|
||||
// 根据状态生成不同颜色图标
|
||||
function makeIcon(status) {
|
||||
const color = status === 'visited' ? '#16a34a' : '#f59e0b';
|
||||
return L.divIcon({
|
||||
className: '',
|
||||
html: `<div style="background:${color};width:16px;height:16px;border-radius:50%;border:2px solid #fff;box-shadow:0 0 4px rgba(0,0,0,.4)"></div>`,
|
||||
iconSize: [16, 16],
|
||||
iconAnchor: [8, 8]
|
||||
});
|
||||
}
|
||||
|
||||
function renderSpot(spot) {
|
||||
if (markers[spot.id]) {
|
||||
map.removeLayer(markers[spot.id]);
|
||||
}
|
||||
const marker = L.marker([spot.lat, spot.lng], { icon: makeIcon(spot.status) }).addTo(map);
|
||||
marker.bindPopup(
|
||||
`<b>${spot.name}</b><br/>状态:${spot.status === 'visited' ? '去过 ✅' : '想去 ⭐'}<br/>` +
|
||||
`<button data-id="${spot.id}" class="popup-toggle">切换状态</button>`
|
||||
);
|
||||
markers[spot.id] = marker;
|
||||
}
|
||||
|
||||
function renderAll() {
|
||||
// 清除旧 marker
|
||||
Object.values(markers).forEach(m => map.removeLayer(m));
|
||||
Object.keys(markers).forEach(k => delete markers[k]);
|
||||
spots.forEach(renderSpot);
|
||||
}
|
||||
|
||||
// 地图点击添加新景点
|
||||
map.on('click', function (e) {
|
||||
const user = window.Auth.currentUser();
|
||||
if (!user) {
|
||||
alert('请先登录后再添加景点标注');
|
||||
return;
|
||||
}
|
||||
const name = prompt('请输入景点名称:');
|
||||
if (!name) return;
|
||||
const spot = {
|
||||
id: 's_' + Date.now() + '_' + Math.floor(Math.random() * 1000),
|
||||
name: name.trim(),
|
||||
lat: e.latlng.lat,
|
||||
lng: e.latlng.lng,
|
||||
status: 'wish'
|
||||
};
|
||||
spots.push(spot);
|
||||
renderSpot(spot);
|
||||
window.MapAPI.onSpotsChange(spots);
|
||||
});
|
||||
|
||||
// 弹窗内切换状态
|
||||
map.on('popupopen', function (e) {
|
||||
const btn = e.popup.getElement().querySelector('.popup-toggle');
|
||||
if (!btn) return;
|
||||
btn.addEventListener('click', function () {
|
||||
const id = btn.getAttribute('data-id');
|
||||
const spot = spots.find(s => s.id === id);
|
||||
if (!spot) return;
|
||||
spot.status = spot.status === 'visited' ? 'wish' : 'visited';
|
||||
renderSpot(spot);
|
||||
window.MapAPI.onSpotsChange(spots);
|
||||
map.closePopup();
|
||||
});
|
||||
});
|
||||
|
||||
// 对外暴露的 API
|
||||
window.MapAPI = {
|
||||
getMap: () => map,
|
||||
getSpots: () => spots,
|
||||
setSpots(newSpots) {
|
||||
spots = newSpots || [];
|
||||
renderAll();
|
||||
},
|
||||
// 由 main.js 覆盖,用于同步到 UI 和存储
|
||||
onSpotsChange: function () {},
|
||||
// 定位到坐标
|
||||
flyTo(lat, lng, zoom) {
|
||||
map.flyTo([lat, lng], zoom || 12);
|
||||
}
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user