提交一下
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user