卫星图层切换页面失效问题和位置变动问题解决

This commit is contained in:
wangxk 2025-06-30 14:11:14 +08:00
parent eb451187ff
commit 8edd88c002

View File

@ -30,6 +30,10 @@ import { L7ChartView } from '@/views/chart/components/js/panel/types/impl/l7'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { ExportImage, Scale, Fullscreen, Control, Scene, TileLayer } from '@antv/l7' import { ExportImage, Scale, Fullscreen, Control, Scene, TileLayer } from '@antv/l7'
import { GaodeMap } from '@antv/l7-maps'; import { GaodeMap } from '@antv/l7-maps';
//
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js' //
const { t } = useI18n() const { t } = useI18n()
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile } = const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile } =
@ -118,7 +122,11 @@ const state = reactive({
let chartData = shallowRef<Partial<Chart['data']>>({ let chartData = shallowRef<Partial<Chart['data']>>({
fields: [] fields: []
}) })
// Three.js
let threeScene: THREE.Scene | null = null;
let threeRenderer: THREE.WebGLRenderer | null = null;
let threeCamera: THREE.PerspectiveCamera | null = null;
let model: THREE.Object3D | null = null;
const containerId = 'container-' + showPosition.value + '-' + view.value.id + '-' + suffixId.value const containerId = 'container-' + showPosition.value + '-' + view.value.id + '-' + suffixId.value
const viewTrack = ref(null) const viewTrack = ref(null)
@ -332,8 +340,51 @@ const renderL7Plot = async (chart: ChartObj, chartView: L7PlotChartView<any, any
emit('resetLoading') emit('resetLoading')
}, 500) }, 500)
} }
// let satelliteLayer: any = null;
let mapL7Timer: number class SatelliteControl extends Control {
protected onAdd() {
// debugger
const btn = document.createElement('button');
btn.className = 'l7-control-button l7-satellite-control';
btn.innerHTML = '卫星';
// btn.title = '';
btn.style.backgroundColor = '#000';
btn.style.color = '#fff';
btn.style.padding = '2px';
btn.style.borderRadius = '4px';
btn.style.cursor = 'pointer'
btn.style.fontSize = '11px';
let scene = myChart.getScene()
console.log('scene', scene)
//
let satelliteLayer = new window.AMap.TileLayer.Satellite();
let isSatelliteVisible = false;
console.log('12345677', satelliteLayer);
btn.onclick = () => {
// console.log('12345677',isSatelliteVisible);
isSatelliteVisible = !isSatelliteVisible;
if (isSatelliteVisible) {
// 使 scene.addLayer
btn.style.backgroundColor = '#409eff';
scene.map.add(satelliteLayer)
} else {
// 使 scene.removeLayer
btn.style.backgroundColor = '#000';
scene.map.remove(satelliteLayer)
}
};
// //
// scene.on('loaded', () => {
// console.log('');
// });
return btn;
}
}
let mapL7Timer: any
let scaleControl: Scale | null = null // let scaleControl: Scale | null = null //
let fullscreenControl let fullscreenControl
let satelliteControlInstance = null; // let satelliteControlInstance = null; //
@ -355,10 +406,6 @@ const renderL7 = async (chart: ChartObj, chartView: L7ChartView<any, any>, callb
}); });
myChart.getScene()?.addControl(scaleControl); myChart.getScene()?.addControl(scaleControl);
} }
//
// //
if (fullscreenControl) { if (fullscreenControl) {
@ -368,60 +415,14 @@ const renderL7 = async (chart: ChartObj, chartView: L7ChartView<any, any>, callb
}); });
myChart.getScene()?.addControl(fullscreenControl, 'bottomright'); myChart.getScene()?.addControl(fullscreenControl, 'bottomright');
} }
// ====== 使API ====== // ====== 使API ======
let satelliteLayer: any = null;
let isSatelliteVisible = false;
class SatelliteControl extends Control {
protected onAdd() {
const btn = document.createElement('button');
btn.className = 'l7-control-button l7-satellite-control';
btn.innerHTML = '卫星';
// btn.title = '';
btn.style.backgroundColor = '#000';
btn.style.color = '#fff';
btn.style.padding = '2px';
btn.style.borderRadius = '4px';
btn.style.cursor = 'pointer'
btn.style.fontSize = '11px';
const scene = myChart.getScene()
//
scene.on('loaded', () => {
//
satelliteLayer = new window.AMap.TileLayer.Satellite();
btn.onclick = () => {
isSatelliteVisible = !isSatelliteVisible;
if (isSatelliteVisible) {
// 使 scene.addLayer
btn.style.backgroundColor = '#409eff';
scene.map.add(satelliteLayer)
} else {
// 使 scene.removeLayer
btn.style.backgroundColor = '#000';
scene.map.remove(satelliteLayer)
}
};
});
return btn;
}
}
// //
// //
if (satelliteControlInstance) { if (!satelliteControlInstance) {
} else {
// //
satelliteControlInstance = new SatelliteControl({ position: 'bottomright' }); satelliteControlInstance = new SatelliteControl({ position: 'bottomright' });
myChart.getScene()?.addControl(satelliteControlInstance); myChart.getScene()?.addControl(satelliteControlInstance);
} }
// ====== ====== // ====== ======
myChart?.render(); myChart?.render();
@ -734,6 +735,138 @@ defineExpose({
trackMenu, trackMenu,
clearLinkage clearLinkage
}) })
// three.js
// - Three.js
const initThree = (container: HTMLElement) => {
//
threeScene = new THREE.Scene();
//
threeCamera = new THREE.PerspectiveCamera(
75,
container.clientWidth / container.clientHeight,
0.1,
1000
);
threeCamera.position.z = 5;
//
threeRenderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
threeRenderer.setSize(container.clientWidth, container.clientHeight);
//
threeRenderer.domElement.style.position = 'absolute';
threeRenderer.domElement.style.top = '0';
threeRenderer.domElement.style.left = '0';
threeRenderer.domElement.style.zIndex = '1'; //
container.appendChild(threeRenderer.domElement);
//
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
threeScene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(10, 10, 10);
threeScene.add(directionalLight);
};
// -
const loadModel = (filePath: string) => {
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('./static/js/')
dracoLoader.setDecoderConfig({ type: 'js' })
loader.setDRACOLoader(dracoLoader)
//
if (!myChart?.getScene()) {
console.warn('地图场景尚未初始化,延迟加载模型');
//
setTimeout(() => loadModel(filePath), 500);
return;
}
const scene = myChart.getScene();
//
if (scene.loaded) {
//
loadModelInternal(loader, filePath);
} else {
//
const loadedHandler = () => {
scene.off('loaded', loadedHandler); //
loadModelInternal(loader, filePath);
};
scene.on('loaded', loadedHandler);
}
};
//
const loadModelInternal = (loader, filePath) => {
loader.load(
filePath,
(gltf) => {
console.log('Model loaded successfully:', gltf);
model = gltf.scene;
threeScene?.add(model);
// animate();
placeModelByLngLat(116.3974, 39.9093); //
},
(progress) => {
console.log('Loading progress:', progress);
},
(error) => {
console.error('模型加载失败:', error);
}
);
};
// -
const placeModelByLngLat = (lng: number, lat: number) => {
debugger
if (!model || !myChart?.getScene()) {
console.warn('模型或地图场景未初始化');
return;
}
const scene = myChart.getScene();
console.log('地图场景状态:', scene);
try {
const containerPoint = scene.lngLatToContainer([lng, lat]);
console.log('容器坐标:', containerPoint);
const container = document.getElementById(containerId);
if (!container) {
console.error('容器元素未找到');
return;
}
// Three.js
const x = (containerPoint.x / container.clientWidth) * 2 - 1;
const y = -(containerPoint.y / container.clientHeight) * 2 + 1;
console.log('Three.js坐标:', { x, y });
//
model.position.set(x * 5, y * 5, 0);
//
if (threeCamera) {
threeCamera.lookAt(model.position);
console.log('相机已调整朝向模型');
}
} catch (e) {
console.error('坐标转换错误:', e);
}
};
//
const animate = () => {
requestAnimationFrame(animate);
if (threeRenderer && threeScene && threeCamera) {
threeRenderer.render(threeScene, threeCamera);
}
};
let resizeObserver let resizeObserver
const TOLERANCE = 0.01 const TOLERANCE = 0.01
const RESIZE_MONITOR_CHARTS = ['map', 'bubble-map', 'flow-map', 'heat-map'] const RESIZE_MONITOR_CHARTS = ['map', 'bubble-map', 'flow-map', 'heat-map']
@ -760,6 +893,15 @@ onMounted(() => {
resizeObserver.observe(containerDom) resizeObserver.observe(containerDom)
useEmitt({ name: 'l7-prepare-picture', callback: preparePicture }) useEmitt({ name: 'l7-prepare-picture', callback: preparePicture })
useEmitt({ name: 'l7-unprepare-picture', callback: unPreparePicture }) useEmitt({ name: 'l7-unprepare-picture', callback: unPreparePicture })
// Three.js
// const container = document.getElementById(containerId);
// if (container) {
// initThree(container);
// //
// // loadModel(`./static/3DModel/Camera1.glb`);
// // loadModel('static/3DModel/scene.glb');
// }
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
try { try {
@ -768,6 +910,9 @@ onBeforeUnmount(() => {
} catch (e) { } catch (e) {
console.warn(e) console.warn(e)
} }
if (threeRenderer) {
threeRenderer.dispose();
}
}) })
</script> </script>
@ -809,6 +954,21 @@ onBeforeUnmount(() => {
fill: #fff !important; fill: #fff !important;
color: #fff !important; color: #fff !important;
} }
:deep(.l7-control-zoom){
position:fixed;
right: 0px;
bottom: 65px;
}
:deep(.l7-control-button){
position:fixed;
right: 0px;
bottom: 35px;
}
// :deep(.l7-button-control){
// position:fixed;
// right: 0px;
// bottom: 0px;
// }
// :deep(.l7-control-container .l7-top) { // :deep(.l7-control-container .l7-top) {
// top: auto !important; // top: auto !important;