卫星图层切换页面失效问题和位置变动问题解决
This commit is contained in:
parent
eb451187ff
commit
8edd88c002
@ -30,6 +30,10 @@ import { L7ChartView } from '@/views/chart/components/js/panel/types/impl/l7'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { ExportImage, Scale, Fullscreen, Control, Scene, TileLayer } from '@antv/l7'
|
||||
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 dvMainStore = dvMainStoreWithOut()
|
||||
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile } =
|
||||
@ -118,7 +122,11 @@ const state = reactive({
|
||||
let chartData = shallowRef<Partial<Chart['data']>>({
|
||||
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 viewTrack = ref(null)
|
||||
|
||||
@ -332,8 +340,51 @@ const renderL7Plot = async (chart: ChartObj, chartView: L7PlotChartView<any, any
|
||||
emit('resetLoading')
|
||||
}, 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 fullscreenControl
|
||||
let satelliteControlInstance = null; // 用于存储卫星控件实例
|
||||
@ -355,10 +406,6 @@ const renderL7 = async (chart: ChartObj, chartView: L7ChartView<any, any>, callb
|
||||
});
|
||||
myChart.getScene()?.addControl(scaleControl);
|
||||
}
|
||||
|
||||
// 创建并添加新比例尺
|
||||
|
||||
|
||||
// 添加全屏控件
|
||||
if (fullscreenControl) {
|
||||
|
||||
@ -368,60 +415,14 @@ const renderL7 = async (chart: ChartObj, chartView: L7ChartView<any, any>, callb
|
||||
});
|
||||
myChart.getScene()?.addControl(fullscreenControl, 'bottomright');
|
||||
}
|
||||
|
||||
|
||||
// ====== 使用高德地图原生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) {
|
||||
|
||||
} else {
|
||||
if (!satelliteControlInstance) {
|
||||
// 添加新的卫星控件到地图
|
||||
satelliteControlInstance = new SatelliteControl({ position: 'bottomright' });
|
||||
myChart.getScene()?.addControl(satelliteControlInstance);
|
||||
}
|
||||
|
||||
|
||||
// ====== 修复完成 ======
|
||||
|
||||
myChart?.render();
|
||||
@ -734,6 +735,138 @@ defineExpose({
|
||||
trackMenu,
|
||||
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
|
||||
const TOLERANCE = 0.01
|
||||
const RESIZE_MONITOR_CHARTS = ['map', 'bubble-map', 'flow-map', 'heat-map']
|
||||
@ -760,6 +893,15 @@ onMounted(() => {
|
||||
resizeObserver.observe(containerDom)
|
||||
useEmitt({ name: 'l7-prepare-picture', callback: preparePicture })
|
||||
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(() => {
|
||||
try {
|
||||
@ -768,6 +910,9 @@ onBeforeUnmount(() => {
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
}
|
||||
if (threeRenderer) {
|
||||
threeRenderer.dispose();
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -809,6 +954,21 @@ onBeforeUnmount(() => {
|
||||
fill: #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) {
|
||||
// top: auto !important;
|
||||
|
Loading…
Reference in New Issue
Block a user