feat: add camera switch, fix click event/dialog resize/map state sync
- fix(engine): adapt click handler to base engine array format data[0].url/ids - feat(toolbar): add perspective/orthographic camera switch button with dynamic icon - fix(dialog): clamp resize to container bounds to prevent overflow - feat(demo): add auto-combine feature with robust URL parsing and validation - fix(walk): close minimap on walk exit and sync map state between toolbar and walk panel - fix(engine): correct MiniMap getstate() casing to match base engine API - build: rebuild demo libs
This commit is contained in:
@@ -200,6 +200,7 @@
|
||||
<button class="primary" onclick="loadModel()">加载模型</button>
|
||||
<button onclick="switchModel()">切换模型</button>
|
||||
<button onclick="loadCombinedModel()">组合模型</button>
|
||||
<button onclick="openCombineDialog()">自动组合</button>
|
||||
</div>
|
||||
<div class="btn-container" style="margin-top: 8px;">
|
||||
<button onclick="pauseRendering()">暂停渲染</button>
|
||||
@@ -216,6 +217,19 @@
|
||||
<div id="app"></div>
|
||||
</main>
|
||||
|
||||
<!-- 自动组合弹窗 -->
|
||||
<div id="combine-overlay" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:9999; display:none; justify-content:center; align-items:center;">
|
||||
<div style="background:#fff; border-radius:10px; padding:24px; width:520px; max-width:90vw; box-shadow:0 8px 32px rgba(0,0,0,.18);">
|
||||
<h3 style="margin:0 0 12px; font-size:1.1rem; color:#333;">自动组合加载</h3>
|
||||
<p style="margin:0 0 10px; font-size:.85rem; color:#888;">请输入模型 URL,每行一个或用英文逗号分隔:</p>
|
||||
<textarea id="combine-urls" rows="6" style="width:100%; padding:10px; font-size:.85rem; border:1px solid #ddd; border-radius:6px; resize:vertical; font-family:monospace;" placeholder="https://example.com/model1/ https://example.com/model2/"></textarea>
|
||||
<div style="display:flex; justify-content:flex-end; gap:8px; margin-top:14px;">
|
||||
<button onclick="closeCombineDialog()" style="min-width:72px;">取消</button>
|
||||
<button class="primary" onclick="confirmCombineLoad()" style="min-width:72px;">确定加载</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let engine = null;
|
||||
let isToolbarVisible = true;
|
||||
@@ -577,6 +591,84 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- 自动组合加载 ---
|
||||
function openCombineDialog() {
|
||||
if (!engine || !engine.engine || !engine.engine.isInitialized()) {
|
||||
alert('请先初始化 3D 引擎!');
|
||||
return;
|
||||
}
|
||||
const overlay = document.getElementById('combine-overlay');
|
||||
overlay.style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeCombineDialog() {
|
||||
const overlay = document.getElementById('combine-overlay');
|
||||
overlay.style.display = 'none';
|
||||
}
|
||||
|
||||
function confirmCombineLoad() {
|
||||
let raw = document.getElementById('combine-urls').value.trim();
|
||||
if (!raw) {
|
||||
alert('请输入至少一个模型 URL');
|
||||
return;
|
||||
}
|
||||
|
||||
// 1) 统一清洗:去除智能引号、零宽字符、BOM 等不可见字符
|
||||
raw = raw
|
||||
.replace(/[\u2018\u2019]/g, "'") // “” → '
|
||||
.replace(/[\u201C\u201D]/g, '"') // “” → "
|
||||
.replace(/[\u200B\uFEFF\u00A0]/g, '') // 零宽空格、BOM、不换行空格
|
||||
.trim();
|
||||
|
||||
// 2) 尝试当 JSON 数组解析
|
||||
let urls = [];
|
||||
try {
|
||||
const jsonStr = raw.replace(/'/g, '"');
|
||||
const parsed = JSON.parse(jsonStr);
|
||||
if (Array.isArray(parsed)) {
|
||||
urls = parsed.map(s => String(s).trim()).filter(Boolean);
|
||||
}
|
||||
} catch(e) {
|
||||
// 3) JSON 失败,走分割逻辑
|
||||
urls = raw.split(/[,;\n\r]+/)
|
||||
.map(s => s.trim().replace(/^['"|\[\]\s]+|['"|\[\]\s]+$/g, ''))
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
// 4) 只保留 http/https 开头的合法 URL
|
||||
urls = urls.filter(s => /^https?:\/\//i.test(s));
|
||||
|
||||
if (urls.length === 0) {
|
||||
alert('未解析到有效的 URL,请确保以 http:// 或 https:// 开头');
|
||||
return;
|
||||
}
|
||||
|
||||
// 5) 逐个校验 URL 是否合法
|
||||
for (let i = 0; i < urls.length; i++) {
|
||||
try {
|
||||
new URL(urls[i]);
|
||||
} catch(e) {
|
||||
alert('第 ' + (i+1) + ' 个 URL 无效:\n' + urls[i] + '\n\n请检查是否包含特殊字符');
|
||||
console.error('❌ 无效 URL,原始字符:', JSON.stringify(urls[i]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
engine.engine.loadModel(urls, {
|
||||
position: [0, 0, 0],
|
||||
rotation: [0, 0, 0],
|
||||
scale: [1, 1, 1]
|
||||
});
|
||||
console.log('✅ 自动组合加载已发送:', urls);
|
||||
closeCombineDialog();
|
||||
document.getElementById('combine-urls').value = '';
|
||||
} catch (error) {
|
||||
console.error('❌ 自动组合加载错误:', error);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user