// 垣曲热点编辑器 v2.2 - 强化兼容性版本 // 解决预览和保存不起作用的问题 (function() { 'use strict'; // 全局配置 const CONFIG = { scenes: { "上库": [ { id: "scene_skxfoyzv", name: "上库" } ], "上库营地": [ { id: "scene_wekxgtaqlxcw", name: "上库营地" } ], "下库全景": [ { id: "scene_welxgtxfoyzv", name: "下库全景" } ], "业主营地": [ { id: "scene_bhz", name: "业主营地及拌合站处" }, { id: "scene_weawehaqlxcw", name: "业主营地" } ], "洞室": [ { id: "scene_wgkbaayae", name: "交通洞" }, { id: "scene_jtdtfd", name: "交通洞 通风洞全景" }, { id: "scene_yaexukxfoyzv", name: "洞室全景" }, { id: "scene_baabjoyae", name: "通风洞" } ], "产业工人营地": [ { id: "scene_wgnweaxdlwggaqlxcw", name: "产业工人营地" }, { id: "scene_chaoshi_quanjing", name: "营地超市全景" }, { id: "scene_canting_quanjing", name: "营地餐厅全景" } ], "垣曲二期抽水蓄能电站": [ { id: "scene_bhfzbuxfoyzv", name: "垣曲二期抽水蓄能电站" } ], "左右岸坝肩全景": [ { id: "scene_zyabj", name: "左右岸坝肩全景" } ], "开关站全景": [ { id: "scene_kgzsc", name: "开关站上侧" }, { id: "scene_xiaxfzzrz_xfoyzv", name: "开关站 全景" } ] } }; // 日志函数 function log(message, type = 'info') { const timestamp = new Date().toLocaleTimeString(); console.log(`[${timestamp}] [热点编辑器] ${message}`); if (type === 'error') { console.error(`[${timestamp}] [热点编辑器] ❌ ${message}`); } } // Krpano 检查函数 function checkKrpano() { try { if (!window.krpano) { log('Krpano对象未找到', 'error'); return false; } // 尝试调用一个简单的krpano方法 const testCall = krpano.get('xml'); log('Krpano对象验证成功'); return true; } catch (error) { log(`Krpano检查失败: ${error.message}`, 'error'); return false; } } // 安全的krpano调用 function safeKrpanoCall(command) { try { if (!checkKrpano()) { throw new Error('Krpano不可用'); } log(`执行krpano命令: ${command}`); const result = krpano.call(command); log(`命令执行成功`); return result; } catch (error) { log(`命令执行失败: ${error.message}`, 'error'); throw error; } } // 安全的krpano属性设置 function safeKrpanoSet(property, value) { try { if (!checkKrpano()) { throw new Error('Krpano不可用'); } log(`设置krpano属性: ${property} = ${value}`); krpano.set(property, value); log(`属性设置成功`); } catch (error) { log(`属性设置失败: ${error.message}`, 'error'); throw error; } } // 安全的krpano属性获取 function safeKrpanoGet(property) { try { if (!checkKrpano()) { throw new Error('Krpano不可用'); } const value = krpano.get(property); log(`获取krpano属性: ${property} = ${value}`); return value; } catch (error) { log(`属性获取失败: ${error.message}`, 'error'); throw error; } } // 热点编辑器类 class HotspotEditor { constructor() { this.isReady = false; this.isOpen = false; this.previewId = 'yuanqu_preview_' + Date.now(); this.init(); } init() { try { if (document.getElementById('yuanqu-hotspot-editor-v22')) { log('编辑器已存在,跳过初始化'); this.isReady = true; return; } this.createUI(); this.bindEvents(); this.isReady = true; log('热点编辑器初始化完成'); } catch (error) { log(`初始化失败: ${error.message}`, 'error'); } } createUI() { const html = ` `; document.body.insertAdjacentHTML('beforeend', html); log('UI界面创建完成'); } generateSceneOptions() { let options = ''; Object.entries(CONFIG.scenes).forEach(([group, scenes]) => { options += ``; scenes.forEach(scene => { options += ``; }); options += ''; }); return options; } bindEvents() { const editor = document.getElementById('yuanqu-hotspot-editor-v22'); // 关闭事件 editor.querySelector('.close-btn').onclick = () => this.hide(); editor.querySelector('.cancel-btn').onclick = () => this.hide(); editor.querySelector('.overlay').onclick = () => this.hide(); // 功能按钮 editor.querySelector('.get-view-btn').onclick = () => this.getCurrentView(); editor.querySelector('.preview-btn').onclick = () => this.preview(); editor.querySelector('.save-btn').onclick = () => this.save(); log('事件绑定完成'); } show() { if (!this.isReady) { this.showMessage('编辑器未准备就绪', 'error'); return; } const editor = document.getElementById('yuanqu-hotspot-editor-v22'); editor.style.display = 'block'; this.isOpen = true; // 清空表单 this.clearForm(); log('编辑器已显示'); } hide() { const editor = document.getElementById('yuanqu-hotspot-editor-v22'); editor.style.display = 'none'; this.isOpen = false; // 清除预览热点 this.clearPreview(); log('编辑器已隐藏'); } clearForm() { const editor = document.getElementById('yuanqu-hotspot-editor-v22'); editor.querySelector('.name-input').value = ''; editor.querySelector('.scene-select').value = ''; editor.querySelector('.ath-input').value = ''; editor.querySelector('.atv-input').value = ''; this.hideMessage(); } getCurrentView() { try { log('开始获取当前视角'); const ath = parseFloat(safeKrpanoGet('view.hlookat')).toFixed(1); const atv = parseFloat(safeKrpanoGet('view.vlookat')).toFixed(1); const editor = document.getElementById('yuanqu-hotspot-editor-v22'); editor.querySelector('.ath-input').value = ath; editor.querySelector('.atv-input').value = atv; this.showMessage(`📷 已获取视角: 水平 ${ath}°, 垂直 ${atv}°`, 'success'); log(`视角获取成功: ath=${ath}, atv=${atv}`); } catch (error) { log(`获取视角失败: ${error.message}`, 'error'); this.showMessage('❌ 获取视角失败: ' + error.message, 'error'); } } validateForm() { const editor = document.getElementById('yuanqu-hotspot-editor-v22'); const name = editor.querySelector('.name-input').value.trim(); const scene = editor.querySelector('.scene-select').value; const ath = editor.querySelector('.ath-input').value; const atv = editor.querySelector('.atv-input').value; if (!name) { this.showMessage('⚠️ 请输入热点名称', 'warning'); return null; } if (!scene) { this.showMessage('⚠️ 请选择目标场景', 'warning'); return null; } if (!ath || !atv) { this.showMessage('⚠️ 请设置热点位置', 'warning'); return null; } if (isNaN(ath) || isNaN(atv)) { this.showMessage('❌ 位置必须是数字', 'error'); return null; } return { name, scene, ath: parseFloat(ath), atv: parseFloat(atv) }; } preview() { try { log('开始预览热点'); const data = this.validateForm(); if (!data) return; // 清除之前的预览 this.clearPreview(); // 创建预览热点 safeKrpanoCall(`addhotspot(${this.previewId})`); safeKrpanoSet(`hotspot[${this.previewId}].style`, 'text'); safeKrpanoSet(`hotspot[${this.previewId}].html`, '🎯'); safeKrpanoSet(`hotspot[${this.previewId}].css`, 'font-size:30px; color:#ff4444;'); safeKrpanoSet(`hotspot[${this.previewId}].ath`, data.ath); safeKrpanoSet(`hotspot[${this.previewId}].atv`, data.atv); safeKrpanoSet(`hotspot[${this.previewId}].tooltip`, `预览: ${data.name}`); // 添加闪烁动画 safeKrpanoCall(`tween(hotspot[${this.previewId}].alpha, 0.3, 0.5, 0, loop(-1, swing));`); this.showMessage('👁️ 预览热点已显示,将在5秒后自动移除', 'info'); log('预览热点创建成功'); // 5秒后自动移除 setTimeout(() => { this.clearPreview(); }, 5000); } catch (error) { log(`预览失败: ${error.message}`, 'error'); this.showMessage('❌ 预览失败: ' + error.message, 'error'); } } save() { try { log('开始保存热点'); const data = this.validateForm(); if (!data) return; const hotspotId = `yuanqu_hs_${Date.now()}`; const sceneName = this.getSceneName(data.scene); log(`创建热点: ${hotspotId}`); // 创建热点 safeKrpanoCall(`addhotspot(${hotspotId})`); safeKrpanoSet(`hotspot[${hotspotId}].style`, 'text'); safeKrpanoSet(`hotspot[${hotspotId}].html`, '🔗'); safeKrpanoSet(`hotspot[${hotspotId}].css`, 'font-size:24px; color:#007bff; cursor:pointer;'); safeKrpanoSet(`hotspot[${hotspotId}].ath`, data.ath); safeKrpanoSet(`hotspot[${hotspotId}].atv`, data.atv); safeKrpanoSet(`hotspot[${hotspotId}].tooltip`, `${data.name} → ${sceneName}`); // 设置点击事件 - 使用最简单的语法 safeKrpanoSet(`hotspot[${hotspotId}].onclick`, `loadscene(${data.scene});`); // 设置悬浮效果 safeKrpanoSet(`hotspot[${hotspotId}].onover`, 'tween(scale, 1.3, 0.3);'); safeKrpanoSet(`hotspot[${hotspotId}].onout`, 'tween(scale, 1.0, 0.3);'); // 确保热点可交互 safeKrpanoSet(`hotspot[${hotspotId}].capture`, true); safeKrpanoSet(`hotspot[${hotspotId}].handcursor`, true); safeKrpanoSet(`hotspot[${hotspotId}].enabled`, true); safeKrpanoSet(`hotspot[${hotspotId}].visible`, true); this.showMessage(`🎉 热点"${data.name}"保存成功!`, 'success'); log(`热点保存成功: ${hotspotId} → ${data.scene}`); // 2秒后关闭 setTimeout(() => { this.hide(); }, 2000); } catch (error) { log(`保存失败: ${error.message}`, 'error'); this.showMessage('❌ 保存失败: ' + error.message, 'error'); } } clearPreview() { try { safeKrpanoCall(`removehotspot(${this.previewId})`); log('预览热点已清除'); } catch (error) { // 忽略清除错误 log(`清除预览时出错: ${error.message}`); } } getSceneName(sceneId) { for (const group of Object.values(CONFIG.scenes)) { const scene = group.find(s => s.id === sceneId); if (scene) return scene.name; } return sceneId; } showMessage(text, type = 'info') { const editor = document.getElementById('yuanqu-hotspot-editor-v22'); const status = editor.querySelector('.status'); status.textContent = text; status.style.display = 'block'; const styles = { success: { bg: '#d4edda', color: '#155724', border: '#c3e6cb' }, error: { bg: '#f8d7da', color: '#721c24', border: '#f5c6cb' }, warning: { bg: '#fff3cd', color: '#856404', border: '#ffeaa7' }, info: { bg: '#d1ecf1', color: '#0c5460', border: '#bee5eb' } }; const style = styles[type] || styles.info; status.style.background = style.bg; status.style.color = style.color; status.style.border = `1px solid ${style.border}`; // 3秒后隐藏 setTimeout(() => { status.style.display = 'none'; }, 3000); } hideMessage() { const editor = document.getElementById('yuanqu-hotspot-editor-v22'); const status = editor.querySelector('.status'); status.style.display = 'none'; } } // 等待DOM加载完成 function initWhenReady() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { window.yuanquHotspotEditor = new HotspotEditor(); log('编辑器在DOM完成后初始化'); }); } else { window.yuanquHotspotEditor = new HotspotEditor(); log('编辑器立即初始化'); } } // 导出全局函数 window.showHotspotEditor = function() { if (!window.yuanquHotspotEditor) { log('编辑器未初始化,正在初始化...', 'error'); window.yuanquHotspotEditor = new HotspotEditor(); } window.yuanquHotspotEditor.show(); }; window.closeHotspotEditor = function() { if (window.yuanquHotspotEditor) { window.yuanquHotspotEditor.hide(); } }; // 初始化 initWhenReady(); log('垣曲热点编辑器 v2.2 强化兼容版加载完成'); })();