双击模型上传到地图和模型在地图上的选定
This commit is contained in:
parent
22a311bd21
commit
c09321e258
@ -1,13 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
<div class="all_conter">
|
<div class="all_conter">
|
||||||
<el-button type="primary" @click="importclick()" style="width: 200px;">导入三维模型</el-button>
|
<el-button type="primary" @click="importclick()" style="width: 200px;">上传三维模型</el-button>
|
||||||
<input type="file" id="avatar" style="display:none" @change="changeFiless">
|
<input type="file" id="avatar" style="display:none" @change="changeFiless">
|
||||||
</div>
|
</div>
|
||||||
<el-scrollbar height="59vh">
|
<el-scrollbar height="59vh">
|
||||||
<div class="model-container">
|
<div class="model-container">
|
||||||
<div v-for="(model, index) in modelAll" :key="index" class="model-wrapper">
|
<!-- -->
|
||||||
<div class="positionbutton" @click="deleteModel(index)">删除</div>
|
<div v-for="(model, index) in modelAll" :key="index" class="model-wrapper" @dblclick="putInModel(model, index)">
|
||||||
|
<div class="positionbutton" @click.stop="deleteModel(index)">删除</div>
|
||||||
<div :ref="(el) => setCanvasRef(el, index)" class="model-canvas"></div>
|
<div :ref="(el) => setCanvasRef(el, index)" class="model-canvas"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -16,21 +17,40 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
|
import { ref, onMounted, onBeforeUnmount, nextTick,PropType,toRefs,computed } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
|
||||||
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
|
||||||
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
|
||||||
import { uploadFileResult } from '@/api/staticResource'
|
import { uploadFileResult } from '@/api/staticResource'
|
||||||
|
import { BASE_VIEW_CONFIG } from '@/views/chart/components/editor/util/chart'
|
||||||
//保存 1.拿数据
|
//保存 1.拿数据
|
||||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { imgUrlTrans } from '@/utils/imgUtils'
|
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||||
|
const { t } = useI18n()
|
||||||
|
// import eventBus from '@/utils/eventBus'
|
||||||
const dvMainStore = dvMainStoreWithOut()
|
const dvMainStore = dvMainStoreWithOut()
|
||||||
const { curComponent } = storeToRefs(dvMainStore)
|
const {
|
||||||
|
curComponent,
|
||||||
|
mobileInPc,
|
||||||
|
componentData
|
||||||
|
} = storeToRefs(dvMainStore)
|
||||||
const snapshotStore = snapshotStoreWithOut()
|
const snapshotStore = snapshotStoreWithOut()
|
||||||
|
const props = defineProps({
|
||||||
|
view: {
|
||||||
|
type: Object as PropType<ChartObj>,
|
||||||
|
required: false,
|
||||||
|
default() {
|
||||||
|
return { ...BASE_VIEW_CONFIG }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const { view } = toRefs(props)
|
||||||
// 模型路径
|
// 模型路径
|
||||||
let threeModel: any = ref([])
|
let threeModel: any = ref([])
|
||||||
let modelAll: any = ref([])
|
let modelAll: any = ref([])
|
||||||
@ -122,16 +142,20 @@ function importclick() {
|
|||||||
const avatar = document.getElementById('avatar');
|
const avatar = document.getElementById('avatar');
|
||||||
avatar?.click();
|
avatar?.click();
|
||||||
}
|
}
|
||||||
|
//保存之前页面保存
|
||||||
|
function saveModel(model: any) {
|
||||||
|
curComponent.value.threeModel = model
|
||||||
|
snapshotStore.recordSnapshotCacheToMobile('threeModel')
|
||||||
|
batchOptChange('threeModel')
|
||||||
|
}
|
||||||
function changeFiless(e: any) {
|
function changeFiless(e: any) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const files = new FormData()
|
const files = new FormData()
|
||||||
files.append('file', e.target.files[0])
|
files.append('file', e.target.files[0])
|
||||||
uploadFileResult(e.target.files[0], fileUrl => {
|
uploadFileResult(e.target.files[0], fileUrl => {
|
||||||
threeModel.value.push({ path: fileUrl })
|
threeModel.value.push({ path: fileUrl, display: false })
|
||||||
modelAll.value = getmodelurl(threeModel.value)
|
modelAll.value = getmodelurl(threeModel.value)
|
||||||
curComponent.value.threeModel = threeModel.value
|
saveModel(threeModel.value)
|
||||||
snapshotStore.recordSnapshotCacheToMobile('threeModel')
|
|
||||||
batchOptChange('threeModel')
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 手动重新渲染新添加的模型
|
// 手动重新渲染新添加的模型
|
||||||
const newIndex = modelAll.value.length - 1
|
const newIndex = modelAll.value.length - 1
|
||||||
@ -152,7 +176,7 @@ function getmodelurl(modelPath: any) {
|
|||||||
})
|
})
|
||||||
return urlArr
|
return urlArr
|
||||||
}
|
}
|
||||||
const batchOptChange = (custom, property, value, subProp?) => {
|
const batchOptChange = (custom: any, property, value, subProp?) => {
|
||||||
dvMainStore.setChangeProperties({
|
dvMainStore.setChangeProperties({
|
||||||
custom: custom,
|
custom: custom,
|
||||||
property: property,
|
property: property,
|
||||||
@ -190,15 +214,64 @@ const deleteModel = (index: number) => {
|
|||||||
// 删除数据源中的模型
|
// 删除数据源中的模型
|
||||||
threeModel.value.splice(index, 1)
|
threeModel.value.splice(index, 1)
|
||||||
modelAll.value.splice(index, 1)
|
modelAll.value.splice(index, 1)
|
||||||
|
saveModel(threeModel.value)
|
||||||
// 同步保存到 Pinia store
|
calcData(view.value, true, 'updateQuery')
|
||||||
curComponent.value.threeModel = threeModel.value
|
|
||||||
snapshotStore.recordSnapshotCacheToMobile('threeModel')
|
|
||||||
batchOptChange('threeModel')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
// 监听 threeModel 的变化
|
|
||||||
|
//触发双击击事件,放入三维模型
|
||||||
|
function putInModel(model: any, index: any) {
|
||||||
|
threeModel.value[index].display = true
|
||||||
|
modelAll.value = getmodelurl(threeModel.value)
|
||||||
|
saveModel(threeModel.value)
|
||||||
|
calcData(view.value, true, 'updateQuery')
|
||||||
|
}
|
||||||
|
//刷新图层事件
|
||||||
|
const calcData = (view, resetDrill = false, updateQuery = '') => {
|
||||||
|
if (
|
||||||
|
view.refreshTime === '' ||
|
||||||
|
parseFloat(view.refreshTime).toString() === 'NaN' ||
|
||||||
|
parseFloat(view.refreshTime) < 1
|
||||||
|
) {
|
||||||
|
ElMessage.error(t('chart.only_input_number'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (resetDrill) {
|
||||||
|
useEmitt().emitter.emit('resetDrill-' + view.id, 0)
|
||||||
|
} else {
|
||||||
|
if (mobileInPc.value) {
|
||||||
|
//移动端设计
|
||||||
|
useEmitt().emitter.emit('onMobileStatusChange', {
|
||||||
|
type: 'componentStyleChange',
|
||||||
|
value: { type: 'calcData', component: JSON.parse(JSON.stringify(view)) }
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
useEmitt().emitter.emit('calcData-' + view.id, view)
|
||||||
|
snapshotStore.recordSnapshotCache('renderChart', view.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snapshotStore.recordSnapshotCache('calcData', view.id)
|
||||||
|
if (updateQuery === 'updateQuery') {
|
||||||
|
queryList.value.forEach(ele => {
|
||||||
|
useEmitt().emitter.emit(`updateQueryCriteria${ele.id}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const queryList = computed(() => {
|
||||||
|
let arr = []
|
||||||
|
componentData.value.forEach(com => {
|
||||||
|
if (com.innerType === 'VQuery') {
|
||||||
|
arr.push(com)
|
||||||
|
}
|
||||||
|
if ('DeTabs' === com.innerType) {
|
||||||
|
com.propValue.forEach(itx => {
|
||||||
|
arr = [...itx.componentData.filter(item => item.innerType === 'VQuery'), ...arr]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return arr
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
threeModel.value = curComponent.value.threeModel ? curComponent.value.threeModel : []
|
threeModel.value = curComponent.value.threeModel ? curComponent.value.threeModel : []
|
||||||
@ -211,7 +284,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
|
calcData(view.value, true, 'updateQuery')
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
@ -8,19 +8,23 @@ import { MAP_EDITOR_PROPERTY_INNER } from '@/views/chart/components/js/panel/cha
|
|||||||
import {
|
import {
|
||||||
parseJson,
|
parseJson,
|
||||||
} from '@/views/chart/components/js/util'
|
} from '@/views/chart/components/js/util'
|
||||||
import { deepCopy } from '@/utils/utils'
|
|
||||||
import { Scene } from '@antv/l7-scene'
|
import { Scene } from '@antv/l7-scene'
|
||||||
import {
|
import {
|
||||||
getMapCenter,
|
getMapCenter,
|
||||||
getMapScene,
|
getMapScene,
|
||||||
getMapStyle,
|
getMapStyle,
|
||||||
mapRendered
|
|
||||||
} from '@/views/chart/components/js/panel/common/common_antv'
|
} from '@/views/chart/components/js/panel/common/common_antv'
|
||||||
import { HeatmapLayer } from '@antv/l7-layers'
|
// import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||||
import { DEFAULT_BASIC_STYLE } from '@/views/chart/components/editor/util/chart'
|
// import { storeToRefs } from 'pinia'
|
||||||
|
// const dvMainStore = dvMainStoreWithOut()
|
||||||
|
// const { curComponent } = storeToRefs(dvMainStore)
|
||||||
/**
|
/**
|
||||||
* 符号地图
|
* 三维地图
|
||||||
*/
|
*/
|
||||||
|
// eventBus.on('createModel', createModel)
|
||||||
|
// function createModel(model){
|
||||||
|
// console.log('jiehsou',model)
|
||||||
|
// }
|
||||||
export class ThreeMap extends L7ChartView<Scene, L7Config> {
|
export class ThreeMap extends L7ChartView<Scene, L7Config> {
|
||||||
properties: EditorProperty[] = [
|
properties: EditorProperty[] = [
|
||||||
'background-overall-component',
|
'background-overall-component',
|
||||||
@ -63,47 +67,33 @@ export class ThreeMap extends L7ChartView<Scene, L7Config> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async drawChart(drawOption: L7DrawConfig<L7Config>) {
|
async drawChart(drawOption: L7DrawConfig<L7Config>) {
|
||||||
// console.log('111111111')
|
|
||||||
// debugger
|
|
||||||
const { chart, container, action } = drawOption
|
const { chart, container, action } = drawOption
|
||||||
const containerDom = document.getElementById(container)
|
const containerDom = document.getElementById(container)
|
||||||
const rect = containerDom?.getBoundingClientRect()
|
const rect = containerDom?.getBoundingClientRect()
|
||||||
// 修改后
|
|
||||||
if (rect?.height <= 0) {
|
if (rect?.height <= 0) {
|
||||||
// 容器不可见时,监听尺寸变化并重试绘制
|
|
||||||
const observer = new ResizeObserver(() => {
|
const observer = new ResizeObserver(() => {
|
||||||
observer.disconnect()
|
observer.disconnect()
|
||||||
this.drawChart(drawOption) // 重新绘制
|
this.drawChart(drawOption)
|
||||||
})
|
})
|
||||||
observer.observe(containerDom)
|
observer.observe(containerDom)
|
||||||
return new L7Wrapper(drawOption.chartObj?.getScene(), [])
|
return new L7Wrapper(drawOption.chartObj?.getScene(), [])
|
||||||
}
|
}
|
||||||
const xAxis = deepCopy(chart.xAxis)
|
|
||||||
let basicStyle
|
let basicStyle
|
||||||
let miscStyle
|
let miscStyle
|
||||||
if (chart.customAttr) {
|
if (chart.customAttr) {
|
||||||
basicStyle = parseJson(chart.customAttr).basicStyle
|
basicStyle = parseJson(chart.customAttr).basicStyle
|
||||||
miscStyle = parseJson(chart.customAttr).misc
|
miscStyle = parseJson(chart.customAttr).misc
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapKey = await this.getMapKey()
|
const mapKey = await this.getMapKey()
|
||||||
const mapStyle = getMapStyle(mapKey, basicStyle)
|
const mapStyle = getMapStyle(mapKey, basicStyle)
|
||||||
|
|
||||||
let center = getMapCenter(basicStyle)
|
let center = getMapCenter(basicStyle)
|
||||||
// 联动时,聚焦到数据点,多个取第一个
|
|
||||||
if (
|
|
||||||
chart.chartExtRequest?.linkageFilters?.length &&
|
|
||||||
xAxis?.length === 2 &&
|
|
||||||
chart.data?.tableRow.length
|
|
||||||
) {
|
|
||||||
// 经度
|
|
||||||
const lng = chart.data?.tableRow?.[0][chart.xAxis[0].gisbiName]
|
|
||||||
// 纬度
|
|
||||||
const lat = chart.data?.tableRow?.[0][chart.xAxis[1].gisbiName]
|
|
||||||
center = [lng, lat]
|
|
||||||
}
|
|
||||||
const chartObj = drawOption.chartObj as unknown as L7Wrapper<L7Config, Scene>
|
const chartObj = drawOption.chartObj as unknown as L7Wrapper<L7Config, Scene>
|
||||||
let scene = chartObj?.getScene()
|
let scene = chartObj?.getScene()
|
||||||
|
|
||||||
scene = await getMapScene(
|
scene = await getMapScene(
|
||||||
chart,
|
chart,
|
||||||
scene,
|
scene,
|
||||||
@ -114,32 +104,11 @@ export class ThreeMap extends L7ChartView<Scene, L7Config> {
|
|||||||
mapStyle,
|
mapStyle,
|
||||||
center
|
center
|
||||||
)
|
)
|
||||||
|
|
||||||
this.configZoomButton(chart, scene, mapKey)
|
this.configZoomButton(chart, scene, mapKey)
|
||||||
const config: L7Config = new HeatmapLayer({
|
|
||||||
name: 'line',
|
|
||||||
blend: 'normal',
|
|
||||||
autoFit: !(basicStyle.autoFit === false)
|
|
||||||
})
|
|
||||||
.source(chart.data?.data, {
|
|
||||||
parser: {
|
|
||||||
type: 'json',
|
|
||||||
x: 'x',
|
|
||||||
y: 'y'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.size('value', [0, 1.0]) // weight映射通道
|
|
||||||
.shape(basicStyle.heatMapType ?? DEFAULT_BASIC_STYLE.heatMapType)
|
|
||||||
|
|
||||||
config.style({
|
|
||||||
intensity: basicStyle.heatMapIntensity ?? DEFAULT_BASIC_STYLE.heatMapIntensity,
|
|
||||||
radius: basicStyle.heatMapRadius ?? DEFAULT_BASIC_STYLE.heatMapRadius,
|
|
||||||
rampColors: {
|
|
||||||
colors: basicStyle.colors.reverse(),
|
|
||||||
positions: [0, 0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 1.0]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// const configList: L7Config[] = []
|
|
||||||
scene.render()
|
scene.render()
|
||||||
return new L7Wrapper(scene, config)
|
return new L7Wrapper(scene, []) // 只保留地图底图
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,16 @@ import { isDashboard, trackBarStyleCheck } from '@/utils/canvasUtils'
|
|||||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||||
import { L7ChartView } from '@/views/chart/components/js/panel/types/impl/l7'
|
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} from '@antv/l7'
|
import { ExportImage, Scale, Fullscreen, Control } from '@antv/l7'
|
||||||
|
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||||
|
//三维导入
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||||
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js' // 控制器
|
||||||
|
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const dvMainStore = dvMainStoreWithOut()
|
const dvMainStore = dvMainStoreWithOut()
|
||||||
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile } =
|
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile, curComponent } =
|
||||||
storeToRefs(dvMainStore)
|
storeToRefs(dvMainStore)
|
||||||
const { emitter } = useEmitt()
|
const { emitter } = useEmitt()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -234,7 +240,7 @@ const calcData = async (view, callback) => {
|
|||||||
callback?.()
|
callback?.()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (['bubble-map', 'map', 'flow-map', 'heat-map','three-map'].includes(view.type)) {
|
if (['bubble-map', 'map', 'flow-map', 'heat-map', 'three-map'].includes(view.type)) {
|
||||||
await renderChart(view, callback)
|
await renderChart(view, callback)
|
||||||
}
|
}
|
||||||
callback?.()
|
callback?.()
|
||||||
@ -443,6 +449,17 @@ const renderL7 = async (chart: ChartObj, chartView: L7ChartView<any, any>, callb
|
|||||||
satelliteControlInstance = new SatelliteControl({ position: 'bottomright' });
|
satelliteControlInstance = new SatelliteControl({ position: 'bottomright' });
|
||||||
myChart.getScene()?.addControl(satelliteControlInstance);
|
myChart.getScene()?.addControl(satelliteControlInstance);
|
||||||
}
|
}
|
||||||
|
if (view.value.type == 'three-map') {
|
||||||
|
// debugger
|
||||||
|
if (curComponent.value && curComponent.value.threeModel && curComponent.value.threeModel.length > 0) {
|
||||||
|
curComponent.value.threeModel.forEach((item: any) => {
|
||||||
|
if (item.display) {
|
||||||
|
threel7(imgUrlTrans(item.path))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
// ====== 修复完成 ======
|
// ====== 修复完成 ======
|
||||||
myChart?.render();
|
myChart?.render();
|
||||||
callback?.();
|
callback?.();
|
||||||
@ -450,7 +467,118 @@ const renderL7 = async (chart: ChartObj, chartView: L7ChartView<any, any>, callb
|
|||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//三维模型集成
|
||||||
|
let threeJSLayerRef: any = null
|
||||||
|
let modelthree: any = null
|
||||||
|
const loadedModel = ref<THREE.Group | null>(null)
|
||||||
|
const threel7 = (modelUrl: any) => {
|
||||||
|
const scene = myChart.getScene();
|
||||||
|
scene.registerRenderService(ThreeRender);
|
||||||
|
// 直接创建并保存相机实例
|
||||||
|
threeJSLayerRef = new ThreeLayer({
|
||||||
|
enableMultiPassRenderer: false,
|
||||||
|
onAddMeshes: (threeScene: any, layer: any) => {
|
||||||
|
// 初始化光源
|
||||||
|
threeScene.add(new THREE.AmbientLight(0xffffff));
|
||||||
|
const sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
|
||||||
|
sunlight.position.set(0, 80000000, 100000000);
|
||||||
|
threeScene.add(sunlight);
|
||||||
|
|
||||||
|
// 模型加载配置
|
||||||
|
const manager = new THREE.LoadingManager();
|
||||||
|
manager.setURLModifier((url: any, path: any) => (path || '') + url);
|
||||||
|
|
||||||
|
const loader = new GLTFLoader(manager);
|
||||||
|
const dracoLoader = new DRACOLoader();
|
||||||
|
dracoLoader.setDecoderPath('./static/js/');
|
||||||
|
dracoLoader.setDecoderConfig({ type: 'js' });
|
||||||
|
loader.setDRACOLoader(dracoLoader);
|
||||||
|
|
||||||
|
loader.load(modelUrl, (gltf) => {
|
||||||
|
const gltfScene = gltf.scene;
|
||||||
|
modelthree = gltfScene
|
||||||
|
// 调整模型位置
|
||||||
|
layer.adjustMeshToMap(gltfScene);
|
||||||
|
layer.setMeshScale(gltfScene, 10, 10, 10);
|
||||||
|
layer.setObjectLngLat(gltfScene, [116.397428, 39.91923], 0);
|
||||||
|
gltfScene.updateMatrixWorld(true); // 更新矩阵以保证坐标正确
|
||||||
|
|
||||||
|
// 添加环境光
|
||||||
|
threeScene.add(new THREE.AmbientLight(0xffffff, 0.3));
|
||||||
|
|
||||||
|
// 处理材质
|
||||||
|
gltfScene.traverse((node: any) => {
|
||||||
|
if (node.isMesh) {
|
||||||
|
const material = node.material;
|
||||||
|
if (material.map) {
|
||||||
|
material.map.repeat.set(1, 1);
|
||||||
|
material.map.offset.set(0, 0);
|
||||||
|
material.map.wrapS = THREE.ClampToEdgeWrapping;
|
||||||
|
material.map.wrapT = THREE.ClampToEdgeWrapping;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 确保模型正确加载碰撞体积
|
||||||
|
gltfScene.traverse((child: any) => {
|
||||||
|
if (child.isMesh) {
|
||||||
|
child.geometry.computeBoundingBox();
|
||||||
|
child.geometry.computeBoundingSphere();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加光源
|
||||||
|
const dirLight = new THREE.DirectionalLight(0xffffff, 0.4);
|
||||||
|
dirLight.position.set(50, 100, 50);
|
||||||
|
threeScene.add(dirLight);
|
||||||
|
|
||||||
|
const pointLight = new THREE.PointLight(0xffffff, 0.6, 1000);
|
||||||
|
pointLight.position.set(10, 15, -5);
|
||||||
|
threeScene.add(pointLight);
|
||||||
|
|
||||||
|
const spotLight = new THREE.SpotLight(0xffffff, 0.8);
|
||||||
|
spotLight.position.set(10, 25, 15);
|
||||||
|
threeScene.add(spotLight);
|
||||||
|
loadedModel.value = gltfScene
|
||||||
|
threeScene.add(gltfScene);
|
||||||
|
layer.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).animate(true);
|
||||||
|
|
||||||
|
scene.addLayer(threeJSLayerRef);
|
||||||
|
scene.on('click', (ev) => {
|
||||||
|
const size = scene?.map?.getSize();
|
||||||
|
const mouse = new THREE.Vector2();
|
||||||
|
const raycaster = new THREE.Raycaster();
|
||||||
|
let currentCamera = threeJSLayerRef.getRenderCamera();
|
||||||
|
mouse.x = (ev.pixel.x / size.width) * 2 - 1;
|
||||||
|
mouse.y = -(ev.pixel.y / size.height) * 2 + 1;
|
||||||
|
raycaster.setFromCamera(mouse, currentCamera);
|
||||||
|
const intersects = raycaster.intersectObjects([modelthree], true);
|
||||||
|
if (intersects.length > 0) {
|
||||||
|
const object = intersects[0].object;
|
||||||
|
console.log(object)
|
||||||
|
createBoundingBox(object as THREE.Object3D);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// ====== 三维模型集成完成 ======
|
||||||
|
// 定义包围盒变量
|
||||||
|
const selectedBoundingBox = ref<THREE.BoxHelper | null>(null);
|
||||||
|
|
||||||
|
// 创建包围盒函数
|
||||||
|
function createBoundingBox(model: THREE.Object3D) {
|
||||||
|
// 移除之前的包围盒
|
||||||
|
if (selectedBoundingBox.value) {
|
||||||
|
threeJSLayerRef.scene.remove(selectedBoundingBox.value);
|
||||||
|
selectedBoundingBox.value = null;
|
||||||
|
}
|
||||||
|
// 创建新的包围盒
|
||||||
|
const boxHelper = new THREE.BoxHelper(model, 0xffff00); // 黄色
|
||||||
|
threeJSLayerRef.scene.add(boxHelper);
|
||||||
|
selectedBoundingBox.value = boxHelper;
|
||||||
|
}
|
||||||
|
|
||||||
const pointClickTrans = () => {
|
const pointClickTrans = () => {
|
||||||
if (embeddedCallBack.value === 'yes') {
|
if (embeddedCallBack.value === 'yes') {
|
||||||
@ -760,7 +888,7 @@ defineExpose({
|
|||||||
|
|
||||||
let resizeObserver
|
let resizeObserver
|
||||||
const TOLERANCE = 0.01
|
const TOLERANCE = 0.01
|
||||||
const RESIZE_MONITOR_CHARTS = ['map', 'bubble-map', 'flow-map', 'heat-map','three-map']
|
const RESIZE_MONITOR_CHARTS = ['map', 'bubble-map', 'flow-map', 'heat-map', 'three-map']
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 1. 获取当前图表容器的 DOM 元素
|
// 1. 获取当前图表容器的 DOM 元素
|
||||||
const containerDom = document.getElementById(containerId)
|
const containerDom = document.getElementById(containerId)
|
||||||
@ -808,15 +936,21 @@ onMounted(() => {
|
|||||||
// 6. 预留 Three.js 初始化逻辑(当前未启用)
|
// 6. 预留 Three.js 初始化逻辑(当前未启用)
|
||||||
// 示例:this.initThreeJs()
|
// 示例:this.initThreeJs()
|
||||||
})
|
})
|
||||||
|
// 清理包围盒
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
try {
|
try {
|
||||||
myChart?.destroy()
|
myChart?.destroy();
|
||||||
resizeObserver?.disconnect()
|
resizeObserver?.disconnect();
|
||||||
} catch (e) {
|
|
||||||
console.warn(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
// 移除包围盒
|
||||||
|
if (selectedBoundingBox.value) {
|
||||||
|
threeJSLayerRef.getScene().remove(selectedBoundingBox.value);
|
||||||
|
selectedBoundingBox.value = null;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -192,7 +192,7 @@ const handleNew = newComponentInfo => {
|
|||||||
component.commonBackground.backgroundColor = 'rgba(41, 41, 41, 1)'
|
component.commonBackground.backgroundColor = 'rgba(41, 41, 41, 1)'
|
||||||
}
|
}
|
||||||
changeComponentSizeWithScale(component) //确保组件在不同比例下保持视觉比例协调
|
changeComponentSizeWithScale(component) //确保组件在不同比例下保持视觉比例协调
|
||||||
dvMainStore.addComponent({ component: component, index: undefined })
|
dvMainStore.addComponent({ component: component, index: undefined })//添加组件
|
||||||
adaptCurThemeCommonStyle(component)//用户切换亮/暗色模式时,自动更新所有组件的样式(如文字颜色、背景色)。
|
adaptCurThemeCommonStyle(component)//用户切换亮/暗色模式时,自动更新所有组件的样式(如文字颜色、背景色)。
|
||||||
snapshotStore.recordSnapshotCache('renderChart', component.id)
|
snapshotStore.recordSnapshotCache('renderChart', component.id)
|
||||||
if (state.countTime > 10) {
|
if (state.countTime > 10) {
|
||||||
|
Loading…
Reference in New Issue
Block a user