旅游公司网站建设ppt,免费网络电视直播在线观看,图片上传网站制作,玩具网站的制作一.前言 由于最近在学习three.js,所以观摩了一下掘金#xff0c;csdn等网站上的有关这部分的内容#xff0c;刚好看到一个带你入门three.js——从0到1实现一个3d可视化地图 - 掘金 (juejin.cn)#xff0c;再加上我的专业属性是地理相关#xff0c;可以说是专业对口#xf…一.前言 由于最近在学习three.js,所以观摩了一下掘金csdn等网站上的有关这部分的内容刚好看到一个带你入门three.js——从0到1实现一个3d可视化地图 - 掘金 (juejin.cn)再加上我的专业属性是地理相关可以说是专业对口但文章已经是三年以前写的而且没有在框架底下完成有关three的很多API也发生了更改所以我的思路是来自该篇文章我进行了模仿和相应的修改但是大致没有发生改变可以说是站在前人的肩膀上。
二.预览 三.实现 首先就是开启一个vue项目再npm install --save three再引入一下d3就可以了配置方面没有什么好配置的这方面大家应该是没问题的。将代码写在子组件里再引入到App.vue中展示就可以了。需要注意用到的全国的json数据来自DataV.GeoAtlas地理小工具系列 (aliyun.com)
子组件xx.vue对应代码
templatediv idcontainer refcanvasContainer/divdiv idtooltip reftooltip/div
/templatescript setupimport * as THREE from three;//OrbitControls 是一个附加组件必须显式导入import { OrbitControls } from three/addons/controls/OrbitControls.js;//墨卡托投影转换可以把我们经纬度坐标转换成我们对应平面的2d坐标,d3里面自带墨卡托投影转换//该引入方式是查阅官网得到的import * as d3 from https://cdn.jsdelivr.net/npm/d37/esm;import { onMounted, onUnmounted,ref } from vue;let canvasContainer ref(null);let tooltip ref(null)let scene,camera,renderer,ambientLight,raycaster,mouse;let lastPick null;//初始化摄像机function initCamera(){camera new THREE.PerspectiveCamera(75,canvasContainer.value.offsetWidth / canvasContainer.value.offsetHeight, 0.1, 1000);camera.position.set(0,0,120);camera.lookAt(scene.position);}//初始化rendererfunction initRenderer(){renderer new THREE.WebGLRenderer();renderer.setSize(canvasContainer.value.offsetWidth,canvasContainer.value.offsetHeight)}//初始化灯光function initLight(){ambientLight new THREE.AmbientLight(0xffffff,20);}//加载json数据function loadJson(){const loader new THREE.FileLoader();loader.load(src/assets/中华人民共和国.json,(data){const jsondata JSON.parse(data);generateGeometry(jsondata)console.log(jsondata);})}// 根据JSON数据生成地图几何体function generateGeometry(jsondata){let map new THREE.Object3D();// 使用d3的地图投影const projection d3.geoMercator().center([104.0,37.5]).translate([0,0]);// 遍历每个省份创建几何体jsondata.features.forEach((element){let province new THREE.Object3D();const coordinates element.geometry.coordinates;if(Array.isArray(coordinates[0][0][0])){coordinates.forEach((multiPolygon){multiPolygon.forEach((polygon){const shape new THREE.Shape();const points [];polygon.forEach((coord,i){const [x,y] projection(coord);if(i0) shape.moveTo(x,-y);else shape.lineTo(x,-y);points.push(new THREE.Vector3(x,-y,5));})const lineGeometry new THREE.BufferGeometry().setFromPoints(points);const lineMaterial new THREE.LineBasicMaterial({ color: white });const line new THREE.Line(lineGeometry, lineMaterial);const extrudeSettings { depth: 10, bevelEnabled: false };const geometry new THREE.ExtrudeGeometry(shape, extrudeSettings);const material new THREE.MeshBasicMaterial({ color: #2defff, transparent: true, opacity: 0.6 });const material1 new THREE.MeshBasicMaterial({color: #3480C4,transparent: true,opacity: 0.5,})const mesh new THREE.Mesh(geometry, [material,material1]);province.properties element.properties;province.add(mesh);province.add(line);})})}else if(Array.isArray(coordinates[0][0])){coordinates.forEach((polygon){const shape new THREE.Shape();const points [];polygon.forEach((coord,i){const [x,y] projection(coord);if(i0) shape.moveTo(x,-y);else shape.lineTo(x,-y);points.push(new THREE.Vector3(x,-y,5));})const lineGeometry new THREE.BufferGeometry().setFromPoints(points);const lineMaterial new THREE.LineBasicMaterial({ color: white });const line new THREE.Line(lineGeometry, lineMaterial);const extrudeSettings { depth: 10, bevelEnabled: false };const geometry new THREE.ExtrudeGeometry(shape, extrudeSettings);const material new THREE.MeshBasicMaterial({ color: #2defff, transparent: true, opacity: 0.6 });const material1 new THREE.MeshBasicMaterial({color: #3480C4,transparent: true,opacity: 0.5,})const mesh new THREE.Mesh(geometry, [material,material1]);province.properties element.properties;province.add(mesh);province.add(line);})}map.add(province);})scene.add(map);}// 设置光线投射器和鼠标位置用于检测鼠标悬停对象function setRaycaster(){raycaster new THREE.Raycaster();mouse new THREE.Vector2();const onMouseMove (event) {mouse.x (event.clientX / canvasContainer.value.offsetWidth) * 2 - 1mouse.y -(event.clientY / canvasContainer.value.offsetHeight) * 2 1tooltip.value.style.left event.clientX 2 pxtooltip.value.style.top event.clientY 2 px}window.addEventListener(mousemove, onMouseMove, false)}// 显示或隐藏工具提示function showTip(){if(lastPick){const properties lastPick.object.parent.properties;tooltip.value.textContent properties.name;tooltip.value.style.visibility visible;console.log(tooltip.value.textContent);}else{tooltip.value.style.visibility hidden;}}// 动画循环用于渲染场景和更新状态function animate() {requestAnimationFrame(animate);raycaster.setFromCamera(mouse,camera);const intersects raycaster.intersectObjects(scene.children,true);if (lastPick) {lastPick.object.material[0].color.set(#2defff)lastPick.object.material[1].color.set(#3480C4)}lastPick nulllastPick intersects.find((item) item.object.material item.object.material.length 2)if (lastPick) {lastPick.object.material[0].color.set(0xff0000)lastPick.object.material[1].color.set(0xff0000)}showTip();renderer.render(scene, camera);}//窗口大小改变时更新摄像机的宽高比和渲染器的大小function handleResize(){if(camera renderer canvasContainer.value){camera.aspect canvasContainer.value.offsetWidth / canvasContainer.value.offsetHeight;camera.updateProjectionMatrix();renderer.setSize(canvasContainer.value.offsetWidth, canvasContainer.value.offsetHeight);}}// 组件挂载时的初始化逻辑onMounted((){scene new THREE.Scene();setRaycaster();initLight();scene.add(ambientLight);initCamera();loadJson();initRenderer();canvasContainer.value.appendChild(renderer.domElement);new OrbitControls(camera,canvasContainer.value)animate();window.addEventListener(resize,handleResize)})onUnmounted((){window.removeEventListener(resize,handleResize)})
/scriptstylebody{margin: 0;padding: 0;overflow: hidden;}#container{/* border: 1px solid black; */width: 100vw;height: 100vh;}#tooltip {position: absolute;z-index: 2;background: white;padding: 10px;border-radius: 5px;visibility: hidden;}
/style
注意在用JSON数据生成地图集合体时分两种情况是因为:
不同省份数据数组嵌套的层数不一样类似于下面这两地 四.总结 共勉如果对于实现的步骤还有疑惑可以转至我在前言分享的那篇文章 它对于实现步骤更详细可以结合着看。