// 引入构造器 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' init() { this.setControls() } setControls() { this.controls = new OrbitControls(this.camera, this.renderer.domElement) // 太灵活了 , 来个阻尼 this.controls.enableDamping = true; this.controls.dampingFactor = 0.1; }
文章插图
controls
好了 , 现在就可以想看哪儿就看哪儿了 。
三、当鼠标移入地图时让对应的地区高亮
Raycaster —— 光线投射Raycaster
文档链接:https://threejs.org/docs/index.html?q=Raycaster#api/zh/core/Raycaster
Raycaster用于进行raycasting(光线投射) 。光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体) 。
这个类有两个方法 ,
第一个setFromCamera(coords, camera)方法 , 它接收两个参数:
coords —— 在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间 。
camera —— 射线所来源的摄像机 。
通过这个方法可以更新射线 。
第二个intersectObjects: 检测所有在射线与这些物体之间 , 包括或不包括后代的相交部分 。返回结果时 , 相交部分将按距离进行排序 , 最近的位于第一个) 。
我们可以通过监听鼠标事件 , 实时更新鼠标的坐标 , 同时实时在渲染函数中更新射线 , 然后通过intersectObjects方法查找当前鼠标移过的物体 。
// 以下是新添加的代码 init() { // 创建场景 this.scene = new THREE.Scene() // 创建相机 this.setCamera() // 创建渲染器 this.setRender() // 创建控制器 this.setControls() // 光线投射 this.setRaycaster() // 加载数据 this.loadData() // 渲染函数 this.render() } setRaycaster() { this.raycaster = new THREE.Raycaster(); this.mouse = new THREE.Vector2(); const onMouse = (event) => { // 将鼠标位置归一化为设备坐标 。x 和 y 方向的取值范围是 (-1 to +1) // threejs的三维坐标系是中间为原点 , 鼠标事件的获得的坐标是左上角为原点 。因此需要在这里转换 this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1 this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1 }; window.addEventListener("mousemove", onMouse, false); } render() { this.raycaster.setFromCamera(this.mouse, this.camera) const intersects = this.raycaster.intersectObjects( this.scene.children, true ) // 如果this.lastPick存在 , 将材质颜色还原 if (this.lastPick) { this.lastPick.object.material[0].color.set(MATERIAL_COLOR1); this.lastPick.object.material[1].color.set(MATERIAL_COLOR2); } // 置空 this.lastPick = null; // 查询当前鼠标移动所产生的射线与物体的焦点 // 有两个material的就是我们要找的对象 this.lastPick = intersects.find( (item) => item.object.material && item.object.material.length === 2 ); // 找到后把颜色换成一个鲜艳的绿色 if (this.lastPick) { this.lastPick.object.material[0].color.set("aquamarine"); this.lastPick.object.material[1].color.set("aquamarine"); } this.renderer.render(this.scene, this.camera) requestAnimationFrame(this.render.bind(this)) }
文章插图
高亮
四、还差一个tooltip
引入 css2DRenderer 和 CSS2DObject , 创建一个2D渲染器 , 用2D渲染器生成一个tooltip 。在此之前 , 需要在 loadData方法创建area时把地区属性添加到Mesh对象上 。确保lastPick对象上能取到地域名称 。
// 把地区属性存到area对象中 area.properties = elem.properties
文章插图
把地区属性存到Mash对象中
【three.js实现3D地图】
// 引入CSS2DObject, CSS2DRenderer import { CSS2DObject, CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer' class Map3D { setRender() { ...... // CSS2DRenderer 创建的是html的div元素 // 这里将div设置成绝对定位 , 盖住canvas画布 this.css2dRenderer = new CSS2DRenderer(); this.css2dRenderer.setSize(window.innerWidth, window.innerHeight); this.css2dRenderer.domElement.style.position = "absolute"; this.css2dRenderer.domElement.style.top = "0px"; this.css2dRenderer.domElement.style.pointerEvents = "none"; document.body.appendChild(this.css2dRenderer.domElement); } render() { // 省略...... this.showTip() this.css2dRenderer.render(this.scene, this.camera) // 省略 ...... } showTip () { if (!this.dom) { this.dom = document.createElement("div"); this.tip = new CSS2DObject(this.dom); } if (this.lastPick) { const { x, y, z } = this.lastPick.point; const properties = this.lastPick.object.parent.properties; // label的样式在直接用css写在样式表中 this.dom.className = "label"; this.dom.innerText = properties.name this.tip.position.set(x + 10, y + 10, z); this.map && this.map.add(this.tip); } } }
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 迟志强|迟志强近况!狱中立志,考政法大学,儿子替他实现狱中心愿
- 苹果戴口罩人脸识别系统可以识别吗? 苹果新版更新可实现戴口罩人脸识别嘛
- 远程控制通过什么实现 远程控制系统可以应用在哪些场合上
- 高德地图支持ar导航的行车记录仪 高德地图ar导航支持的记录仪
- Word表格中如何实现每一页都出现标题行?
- 朱一龙|飞升成功!朱一龙成85后首位金鸡影帝,实现影史留名愿望
- 李帝勋|李帝勋为南宫珉应援 休学入行演戏实现梦想 凭借建筑学概论走红
- 玉龙雪山位于云南哪里 玉龙雪山在云南哪里的地图
- 我国首次实现月球表面软着陆探测器 人类以及探测器登月
- 2012年玛雅预言最后一个为何没实现 玛雅2012预言不算失误