<body>
<div id="Container"></div>
<div id="toolbar" class="param-container tool-bar">
<button type="button" id="active" class="button black">重新投放</button>
<button type="button" id="clear" class="button black">清除投放</button>
<br />
<label><input type="checkbox" id="visibleLine" checked> 显示投放参考线</label>
<br><br>
<div style="margin: 8px 0;"><b>宽度 (°)</b><br><input type="number" id="horizontal" min="1" step="0.1" value="20"></div>
<div style="margin: 8px 0;"><b>高度 (°)</b><br><input type="number" id="vertical" min="1" step="0.1" value="10"></div>
<div style="margin: 8px 0;"><b>投影距离 (m)</b><br><input type="number" id="distance" min="10" step="10" value="350"></div>
<div style="margin-top:15px;"><small>WS URL:</small><br><input id="real-ws" value="ws://ip:40088" style="width:220px;"></div>
<div style="margin-top:8px;"><small>RTSP:</small><br><input id="real-rtsp" value="rtsp://ip:40088/dss/monitor/param/cameraid=1003919%240%26substream=1" style="width:220px;"></div>
</div>
<div style="position: absolute; right: 20px; top: 120px;">
<div id="msChart" style="width: 300px; height: 150px; background:rgba(0,0,0,0.4);"></div>
</div>
<div style="position: absolute; right: 20px; top: 320px;">
<div id="fpsChart" style="width: 300px; height: 150px; background:rgba(0,0,0,0.4);"></div>
</div>
<div id="ws-real-player" style="width:720px; height:480px; visibility:hidden; position:absolute; top:-9999px; left:-9999px;"></div>
<script type="module">
import PlayerManager from './icc/PlayerManager.js';
function onload(SuperMap3D) {
const EngineType = getEngineType();
const viewer = new SuperMap3D.Viewer('Container', { contextOptions: { contextType: Number(EngineType) } });
viewer.scenePromise.then(scene => init(SuperMap3D, scene, viewer));
}
function init(SuperMap3D, scene, viewer) {
viewer.resolutionScale = window.devicePixelRatio;
addBaseMap(viewer);
// 性能监控
const msChart = echarts.init(document.getElementById('msChart'));
const fpsChart = echarts.init(document.getElementById('fpsChart'));
let msData = [], fpsData = [], step = 0;
scene.debugShowFramesPerSecond = true;
scene.shadowMap.darkness = 1.275;
scene.hdrEnabled = false;
scene.sun.show = true;
setInterval(() => {
if (step <= 6 && scene.debugShowFramesPerSecond) {
const msEl = document.querySelector(".supermap3d-performanceDisplay-ms");
const fpsEl = document.querySelector(".supermap3d-performanceDisplay-fps");
if (msEl && fpsEl) {
msData[step] = parseFloat(msEl.innerHTML.replace(/[^0-9.]/g, ''));
fpsData[step] = parseFloat(fpsEl.innerHTML.replace(/[^0-9.]/g, ''));
step++;
}
} else {
step = 0;
}
}, 200);
setInterval(() => {
msChart.setOption({ title: { subtext: 'MS', left: 'right', subtextStyle: { color: '#eee' } }, xAxis: { type: 'category', data: Array(7).fill(''), axisLabel: { color: '#ccc' } }, yAxis: { type: 'value', axisLabel: { color: '#ccc' } }, series: [{ data: msData, type: 'line' }], grid: { left: '5%', right: '5%', top: '25%', bottom: '5%', containLabel: true } });
fpsChart.setOption({ title: { subtext: 'FPS', left: 'right', subtextStyle: { color: '#eee' } }, xAxis: { type: 'category', data: Array(7).fill(''), axisLabel: { color: '#ccc' } }, yAxis: { type: 'value', axisLabel: { color: '#ccc' } }, series: [{ data: fpsData, type: 'line', areaStyle: {} }], grid: { left: '5%', right: '5%', top: '25%', bottom: '5%', containLabel: true } });
}, 1000);
if (!scene.pickPositionSupported) alert('当前浏览器/设备不支持深度拾取,投影功能受限');
// 加载模型
SuperMap3D.when.all([
scene.addS3MTilesLayerByScp(URL_CONFIG.SCP_CBD_BUILD, { name: 'build' }),
scene.addS3MTilesLayerByScp(URL_CONFIG.SCP_CBD_GROUND1, { name: 'ground1' }),
scene.addS3MTilesLayerByScp(URL_CONFIG.SCP_CBD_LAKE, { name: 'lake' }),
scene.addS3MTilesLayerByScp(URL_CONFIG.SCP_CBD_TREE, { name: 'tree' }),
scene.addS3MTilesLayerByScp(URL_CONFIG.SCP_CBD_ROAD, { name: 'road' }),
scene.addS3MTilesLayerByScp(URL_CONFIG.SCP_CBD_BRIDGE, { name: 'bridge' })
], layers => {
scene.camera.setView({ destination: SuperMap3D.Cartesian3.fromDegrees(116.4486, 39.9092, 91.3293), orientation: { heading: 3.179304500963121, pitch: -0.46239072362282485, roll: 6.283185307179583 } });
layers.forEach(l => l.selectEnabled = false);
const perfEl = document.querySelector(".supermap3d-performanceDisplay");
if (perfEl) perfEl.style.display = "none";
// 核心:视频投影对象
const projectionImage = new SuperMap3D.ProjectionImage(scene);
const targetLon = 116.4486895458964;
const targetLat = 39.907729088565965;
const targetHeight = 32.51768911137742;
// WSPlayer 初始化
const realPlayer = new PlayerManager({
el: "ws-real-player",
type: 'real',
maxNum: 1,
num: 1,
showControl: false,
prefixUrl: 'lib',
receiveMessageFromWSPlayer: (method, data, err) => {
if (method === 'initializationCompleted') {
realPlayer.setPlayerAdapter("stretching");
playVideoAndProject();
} else if (method === 'realSuccess') {
console.log("视频流播放成功,开始构建投影");
const videoEl = document.querySelector('#ws-real-player video');
if (videoEl) {
projectionImage.setImage({ video: videoEl });
projectionImage.build();
}
} else if (method === 'realError') {
console.error("视频流失败", err);
}
}
});
function projectToFixedPoint() {
const cameraPos = scene.camera.positionCartographic;
const viewPos = [SuperMap3D.Math.toDegrees(cameraPos.longitude), SuperMap3D.Math.toDegrees(cameraPos.latitude), cameraPos.height];
projectionImage.viewPosition = viewPos;
projectionImage.horizontalFov = Number($("#horizontal").val());
projectionImage.verticalFov = Number($("#vertical").val());
projectionImage.distance = Number($("#distance").val());
projectionImage.hintLineVisible = $("#visibleLine").is(":checked");
projectionImage.setDistDirByPoint([targetLon, targetLat, targetHeight]);
}
function playVideoAndProject() {
const wsURL = $("#real-ws").val();
const rtspURL = $("#real-rtsp").val();
realPlayer.realByUrl({ rtspURL, wsURL, selectIndex: 0, channelId: '', streamType: 1, playerAdapter: 'stretching' });
projectToFixedPoint();
}
setTimeout(() => playVideoAndProject(), 1500);
$("#active").click(() => { realPlayer.close(0); setTimeout(playVideoAndProject, 300); });
$("#clear").click(() => { realPlayer.close(0); projectionImage.destroy && projectionImage.destroy(); });
$("#horizontal,#vertical,#distance").on("input", projectToFixedPoint);
$("#visibleLine").on("change", projectToFixedPoint);
});
}
if (typeof SuperMap3D !== 'undefined') {
window.startupCalled = true;
onload(SuperMap3D);
}
</script>
</body>