提交一下

This commit is contained in:
aixianling
2024-07-12 17:59:27 +08:00
parent 8df752e89f
commit f7ee299e95
2 changed files with 79 additions and 154 deletions

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,8 @@ export default {
data() { data() {
return { return {
geoMap: null, geoMap: null,
layers: [] layers: [],
font: null
} }
}, },
computed: { computed: {
@@ -16,7 +17,7 @@ export default {
const {$waitFor, THREE, $loadScript} = window const {$waitFor, THREE, $loadScript} = window
return $waitFor(THREE).then(() => Promise.all([ return $waitFor(THREE).then(() => Promise.all([
`http://10.0.97.209/presource/datascreen/js/three/js/controls/OrbitControls.js`, `http://10.0.97.209/presource/datascreen/js/three/js/controls/OrbitControls.js`,
`http://10.0.97.209/presource/datascreen/js/three/js/renderers/CSS3DRenderer.js`, `http://10.0.97.209/presource/datascreen/js/three/js/renderers/CSS2DRenderer.js`,
`http://10.0.97.209/presource/datascreen/js/three/js/loaders/FontLoader.js`, `http://10.0.97.209/presource/datascreen/js/three/js/loaders/FontLoader.js`,
`http://10.0.97.209/presource/datascreen/js/three/js/geometries/TextGeometry.js`, `http://10.0.97.209/presource/datascreen/js/three/js/geometries/TextGeometry.js`,
].map(e => $loadScript('js', e)))) ].map(e => $loadScript('js', e))))
@@ -26,7 +27,6 @@ export default {
const rootEl = this.$el const rootEl = this.$el
const root = this const root = this
const scale = 4 const scale = 4
const transform = (o, n, t) => new TWEEN.Tween(o).to(n, t).start();
class GeoMap { class GeoMap {
constructor() { constructor() {
@@ -35,10 +35,10 @@ export default {
this.camera = null; // 相机 this.camera = null; // 相机
this.renderer = null; // 渲染器 this.renderer = null; // 渲染器
this.controls = null; // 控制器 this.controls = null; // 控制器
this.mapGroup = []; // 组 this.mapGroup = new THREE.Group(); // 组
this.selectedObject = null; // 当前选中对象
this.loopIndex = 0; // 循环标记
this.mouse = new THREE.Vector2(); this.mouse = new THREE.Vector2();
this.font = null;
this.tips = new THREE.Group()
} }
/** /**
@@ -47,21 +47,30 @@ export default {
init() { init() {
this.setScene(); this.setScene();
this.setCamera(); this.setCamera();
this.setLight()
this.setAxes(); this.setAxes();
this.setRenderer(); this.setRenderer();
this.setControl(); this.setControl();
this.makeGround(); this.makeGround();
this.getMap('http://10.0.97.209/blade-visual/map/data?id=1456'); this.getMap('http://10.0.97.209/blade-visual/map/data?id=1456');
this.addMarkers() this.addMarkers()
this.animat(); this.animation();
this.bindMouseEvent() this.bindMouseEvent()
} }
setLight() {
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
this.scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1).normalize();
this.scene.add(directionalLight);
}
/** /**
* @desc 动画循环 * @desc 动画循环
* */ * */
animat() { animation() {
requestAnimationFrame(this.animat.bind(this)); requestAnimationFrame(this.animation.bind(this));
TWEEN.update(); TWEEN.update();
this.controls.update(); this.controls.update();
this.renderer.render(this.scene, this.camera); this.renderer.render(this.scene, this.camera);
@@ -128,7 +137,6 @@ export default {
* */ * */
drawMap(data, border) { drawMap(data, border) {
let that = this; let that = this;
this.mapGroup = new THREE.Group();
this.mapGroup.position.y = 0; this.mapGroup.position.y = 0;
this.scene.add(that.mapGroup); this.scene.add(that.mapGroup);
const extrudeSettings = { const extrudeSettings = {
@@ -154,12 +162,7 @@ export default {
// side: THREE.DoubleSide, // side: THREE.DoubleSide,
transparent: true, wireframe: false transparent: true, wireframe: false
}); });
const blockSideMaterial = new THREE.MeshBasicMaterial({
color: '#002240',
wireframe: false
});
const lineMaterial = new THREE.LineBasicMaterial({color: '#97CAE6'}); const lineMaterial = new THREE.LineBasicMaterial({color: '#97CAE6'});
const areas = []
data.forEach(function (areaData) { data.forEach(function (areaData) {
let areaGroup = new THREE.Group(); let areaGroup = new THREE.Group();
areaGroup.name = 'area'; areaGroup.name = 'area';
@@ -173,17 +176,18 @@ export default {
lineMesh.position.z = 0.201; lineMesh.position.z = 0.201;
areaGroup.add(lineMesh); areaGroup.add(lineMesh);
}); });
// areaGroup.add(that.transLayer(areaData)); const {name, cp} = areaData.data
that.setTips(name, cp[0], cp[1])
// areaGroup.add(that.tipsSprite(areaData)); // areaGroup.add(that.tipsSprite(areaData));
that.mapGroup.add(areaGroup); that.mapGroup.add(areaGroup);
}); });
that.mapGroup.add(that.tips)
const shape = new THREE.Shape(border); const shape = new THREE.Shape(border);
const areaGeometry = new THREE.ExtrudeBufferGeometry(shape, extrudeSettings); const areaGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
// const mesh = new THREE.Mesh(areaGeometry, [blockMaterial, blockSideMaterial]);
const mesh = new THREE.Mesh(areaGeometry, blockMaterial); const mesh = new THREE.Mesh(areaGeometry, blockMaterial);
that.mapGroup.add(mesh) that.mapGroup.add(mesh)
that.mapGroup.scale.set(scale, scale, scale) that.mapGroup.scale.set(scale, scale, scale)
that.mapGroup.position.set(-3, 0, 0) that.mapGroup.position.set(0, 0, 0)
that.scene.add(that.mapGroup); that.scene.add(that.mapGroup);
} }
@@ -191,7 +195,7 @@ export default {
let {bakeStockAmt, longitude, latitude} = item let {bakeStockAmt, longitude, latitude} = item
longitude = Number(longitude || 0).toFixed(6); longitude = Number(longitude || 0).toFixed(6);
latitude = Number(latitude || 0).toFixed(6); latitude = Number(latitude || 0).toFixed(6);
const markerGeometry = new THREE.CircleBufferGeometry(0.015, 32); const markerGeometry = new THREE.CircleGeometry(0.015, 32);
const markerMaterial = new THREE.MeshBasicMaterial({ const markerMaterial = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide, side: THREE.DoubleSide,
blending: THREE.AdditiveBlending, blending: THREE.AdditiveBlending,
@@ -202,26 +206,21 @@ export default {
}); });
const marker = new THREE.Mesh(markerGeometry, markerMaterial); const marker = new THREE.Mesh(markerGeometry, markerMaterial);
const lnglat = this.lnglatToVector3([longitude, latitude]); const lnglat = this.lnglatToVector3([longitude, latitude]);
const v3 = new THREE.Vector3(lnglat[0], lnglat[1], lnglat[2]).multiplyScalar(1.2); let v3 = new THREE.Vector3(lnglat[0], lnglat[1], lnglat[2]).multiplyScalar(1.2);
// marker.scale.set(scale, scale, 1)
marker.data = item marker.data = item
marker.position.set(v3.x, v3.y, 0.201) marker.position.set(v3.x, v3.y, 0.201)
return marker return marker
} }
addMarkers() { addMarkers() {
this.markers = []; this.markers = new THREE.Group();
root.layers.map(layer => { root.layers.map(layer => {
const marker = this.transLayer(layer) const marker = this.transLayer(layer)
this.markers.push(marker) this.markers.add(marker)
this.mapGroup.add(marker)
}) })
this.mapGroup.add(this.markers)
} }
/**
* @desc 坐标转换
* @param lnglat [x,y]
* */
lnglatToVector3(lnglat = []) { lnglatToVector3(lnglat = []) {
if (!this.projection) { if (!this.projection) {
this.projection = d3.geoMercator().center([113.665412, 34.757975]).scale(100).translate([0.3, 0]); this.projection = d3.geoMercator().center([113.665412, 34.757975]).scale(100).translate([0.3, 0]);
@@ -265,6 +264,7 @@ export default {
this.camera.aspect = rootEl.offsetWidth / rootEl.offsetHeight; this.camera.aspect = rootEl.offsetWidth / rootEl.offsetHeight;
this.camera.updateProjectionMatrix(); this.camera.updateProjectionMatrix();
this.renderer.setSize(rootEl.offsetWidth, rootEl.offsetHeight); this.renderer.setSize(rootEl.offsetWidth, rootEl.offsetHeight);
this.labelRenderer.setSize(rootEl.offsetWidth, rootEl.offsetHeight);
} }
rootEl.addEventListener('resize', onWindowResize.bind(this), false); rootEl.addEventListener('resize', onWindowResize.bind(this), false);
@@ -290,17 +290,40 @@ export default {
/** /**
* @desc 鼠标 hover 事件 * @desc 鼠标 hover 事件
* */ * */
makeGround() {
const material = new THREE.MeshBasicMaterial({opacity: 0.5, transparent: true, color: '#07193D'});
const geometry = new THREE.PlaneGeometry(100, 100, 1, 1);
let ground = new THREE.Mesh(geometry, material);
ground.position.x = 0;
ground.position.y = 0;
ground.position.z = -1;
this.scene.add(ground);
ground.receiveShadow = true;
ground.castShadow = true;
}
setTips(text, x, y) {
const textGeometry = new THREE.TextGeometry(text, {
font: root.font,
size: 0.04,
height: 0.02
});
textGeometry.center()
textGeometry.rotateZ(Math.PI / 2)
textGeometry.rotateY(Math.PI / 4)
textGeometry.translate(x, y, 0.25)
const textMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, transparent: true, opacity: 0.8});
const textMesh = new THREE.Mesh(textGeometry, textMaterial);
this.tips.add(textMesh)
}
bindMouseEvent() { bindMouseEvent() {
const that = this, _this = this;
const raycaster = new THREE.Raycaster(); const raycaster = new THREE.Raycaster();
function onMouseMove(event) { const onPointerMove = (event) => {
const {top, left, width, height} = rootEl.getBoundingClientRect(); const {clientWidth: width, clientHeight: height} = rootEl;
// const clientX = event.clientX - left this.mouse.x = (event.clientX / width) * 2 - 1; //标准设备横坐标
// const clientY = event.clientY - top this.mouse.y = -(event.clientY / height) * 2 + 1; //标准设备纵坐标
that.mouse.x = (event.clientX / width) * 2 - 1; //标准设备横坐标
that.mouse.y = -(event.clientY / height) * 2 + 1; //标准设备纵坐标
// const standardVector = new THREE.Vector3(x, y, 0.5); //标准设备坐标 // const standardVector = new THREE.Vector3(x, y, 0.5); //标准设备坐标
// //标准设备坐标转世界坐标 // //标准设备坐标转世界坐标
// const worldVector = standardVector.unproject(that.camera); // const worldVector = standardVector.unproject(that.camera);
@@ -338,127 +361,23 @@ export default {
// } // }
} }
function onPointerMove() {
if (_this.selectedObject) {
_this.selectedObject.material.color.set(0xffffff);
_this.selectedObject = null;
}
if (raycaster) {
const intersects = raycaster.intersectObjects(_this.markers);
console.log(intersects)
if (intersects.length > 0) {
const res = intersects.filter(function (res) {
return res && res.object;
})[intersects.length - 1];
if (res && res.object) {
_this.selectedObject = res.object;
_this.selectedObject.material.color.set('#f00');
}
}
}
}
const onClick = evt => { const onClick = evt => {
// 创建一个射线投射器 // 创建一个射线投射器
raycaster.setFromCamera(this.mouse, this.camera); raycaster.setFromCamera(this.mouse, this.camera);
console.log(raycaster.intersectObjects(this.markers)) console.table(raycaster.ray)
const marker = this.markers.find(e => raycaster.intersectObject(e, true).length > 0) const intersects = raycaster.intersectObjects(this.markers.children)
if (marker) { console.log(intersects)
console.log("选取的点:", marker) intersects.forEach(e => {
const {$glob} = window if (e.visible) {
root.$storeBoard.search.storeCode = marker.data?.storeCode const {$glob} = window
$glob.group = '9f299712-5549-413b-a93b-7c3e3b5bfadb' root.$storeBoard.search.storeCode = marker.data?.storeCode
} $glob.group = '9f299712-5549-413b-a93b-7c3e3b5bfadb'
}
})
} }
window.addEventListener('mousemove', onMouseMove, false); rootEl.addEventListener('pointermove', onPointerMove);
// rootEl.addEventListener('pointermove', onPointerMove);
rootEl.addEventListener('click', onClick); rootEl.addEventListener('click', onClick);
} }
makeGround() {
const material = new THREE.MeshBasicMaterial({opacity: 0.5, transparent: true, color: '#07193D'});
const geometry = new THREE.PlaneGeometry(100, 100, 1, 1);
let ground = new THREE.Mesh(geometry, material);
ground.position.x = 0;
ground.position.y = 0;
ground.position.z = -1;
this.scene.add(ground);
ground.receiveShadow = true;
ground.castShadow = true;
const loader = new THREE.FontLoader();
loader.load('/presource/datascreen/js/three/fonts/PingFang SC_Regular.json', (font) => {
const textGeometry = new THREE.TextGeometry('郑州市', {
font: font,
size: 1,
height: 0.2,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.01,
bevelSize: 0.02,
bevelOffset: 0,
bevelSegments: 5
});
textGeometry.translate(1, 0, 3.2)
textGeometry.rotateX(Math.PI / 2)
textGeometry.rotateZ(Math.PI / 2)
const textMaterial = new THREE.MeshPhongMaterial({color: 0xffffff});
const text = new THREE.Mesh(textGeometry, textMaterial);
this.scene.add(text);
// const planeGeometry = new THREE.PlaneGeometry(textGeometry.boundingBox.max.x, textGeometry.boundingBox.max.y);
// const planeMaterial = new THREE.MeshBasicMaterial({color: '#07193D', side: THREE.DoubleSide});
// const plane = new THREE.Mesh(planeGeometry, planeMaterial);
// plane.position.copy(text.position).add(new THREE.Vector3(0, -textGeometry.boundingBox.max.y, 0));
// plane.position.set(0, 0, 0);
// this.scene.add(plane);
})
// const div = document.createElement("div");
// div.style.color = "#fff";
// div.style.width = "40px";
// div.style.height = "25px";
// div.style.borderWidth = "1px";
// div.style.borderStyle = "solid";
// div.style.borderColor = "#00ffc4";
// div.style.borderRadius = "5px";
// div.style.fontSize = "14px";
// div.style.fontWeight = 600;
// div.style.textShadow = "1px 1px 6px #fff";
// div.style.textAlign = "center";
// div.style.lineHeight = "25px";
// div.textContent = `我操你大爷`;
// const tip = new THREE.CSS3DObject(div);
// tip.scale.set(0.01, 0.01, 0.01);
// tip.position.set(0, 0, 1);
// this.scene.add(tip);
}
tipsSprite(areaData) {
let canvas = document.createElement("canvas");
canvas.width = 500;
canvas.height = 60;
document.body.appendChild(canvas);
let ctx = canvas.getContext("2d");
ctx.fillStyle = "#ffffff";
ctx.font = "20px Arial";
ctx.textAlign = "center";
ctx.fillText(areaData.data.name, 250, 40);
let texture = new THREE.CanvasTexture(canvas);
texture.needsUpdate = true;
let SpriteMaterial = new THREE.SpriteMaterial({
map: texture,
depthTest: false,
});
let textSprite = new THREE.Sprite(SpriteMaterial);
textSprite.position.set(areaData.data.cp[0], areaData.data.cp[1], 1);
textSprite.scale.set(4, 0.5, 1);
textSprite.renderOrder = 3;
return textSprite
}
} }
return new GeoMap() return new GeoMap()
@@ -484,14 +403,19 @@ export default {
} }
}, },
mounted() { mounted() {
this.loadLib().then(() => { this.loadLib().then(() => new Promise(resolve => {
const loader = new THREE.FontLoader();
loader.load("/presource/datascreen/js/three/fonts/HarmonyOS Sans SC_Regular.json", font => {
this.font = font
resolve()
})
})).then(() => {
this.geoMap = this.initMap(); this.geoMap = this.initMap();
this.geoMap.init(); this.geoMap.init();
}) })
} }
} }
</script> </script>
<template> <template>
<section class="AppThreeMap"/> <section class="AppThreeMap"/>
</template> </template>