基于Three.js制作一個(gè)3D中國(guó)地圖
不想看繁瑣步驟的,可以直接去github
下載項(xiàng)目,如果可以順便來(lái)個(gè)star
哈哈
本項(xiàng)目使用vue-cli
創(chuàng)建,但不影響使用,主要繪制都已封裝成類
1.使用geoJson繪制3d地圖
1.1 創(chuàng)建場(chǎng)景相關(guān)
// 創(chuàng)建webGL渲染器 this.renderer = new THREE.WebGLRenderer( { antialias: true,alpha: true} ); this.renderer.shadowMap.enabled = true; // 開(kāi)啟陰影 this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; this.renderer.toneMapping = THREE.ACESFilmicToneMapping; this.renderer.toneMappingExposure = 1.25; // 根據(jù)自己的需要調(diào)整顏色模式 // this.renderer.outputEncoding = THREE.sRGBEncoding; this.renderer.outputEncoding = THREE.sHSVEncoding; this.renderer.setPixelRatio( window.devicePixelRatio ); // 清除背景色,透明背景 this.renderer.setClearColor(0xffffff, 0); this.renderer.setSize(this.width, this.height); // 場(chǎng)景 this.scene = new THREE.Scene(); this.scene.background = null // 相機(jī) 透視相機(jī) this.camera = new THREE.PerspectiveCamera(45, this.width / this.height, 0.1, 5000); this.camera.position.set(0, -40, 70); this.camera.lookAt(0, 0, 0);
1.2 根據(jù)json繪制地圖
利用THREE.Shape
繪制地圖的平面邊數(shù)據(jù),再用THREE.ExtrudeGeometry
將一個(gè)面拉高成3d模型,3d餅圖同理也可以這么制作
let jsonData = require('./json/china.json') this.initMap(jsonData); // initMap 方法主要部分 initMap(chinaJson) { /* ...省略 ... */ chinaJson.features.forEach((elem, index) => { // 定一個(gè)省份3D對(duì)象 const province = new THREE.Object3D(); // 每個(gè)的 坐標(biāo) 數(shù)組 const { coordinates } = elem.geometry; const color = COLOR_ARR[index % COLOR_ARR.length] // 循環(huán)坐標(biāo)數(shù)組 coordinates.forEach(multiPolygon => { multiPolygon.forEach((polygon) => { const shape = new THREE.Shape(); for (let i = 0; i < polygon.length; i++) { let [x, y] = projection(polygon[i]); if (i === 0) { shape.moveTo(x, -y); } shape.lineTo(x, -y); } const extrudeSettings = { depth: 4, bevelEnabled: true, bevelSegments: 1, bevelThickness: 0.2 }; const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); // 平面部分材質(zhì) const material = new THREE.MeshStandardMaterial( { metalness: 1, color: color, } ); // 拉高部分材質(zhì) const material1 = new THREE.MeshStandardMaterial( { metalness: 1, roughness: 1, color: color, } ); const mesh = new THREE.Mesh(geometry, [ material, material1 ]); // 設(shè)置高度將省區(qū)分開(kāi)來(lái) if (index % 2 === 0) { mesh.scale.set(1, 1, 1.2); } // 給mesh開(kāi)啟陰影 mesh.castShadow = true mesh.receiveShadow = true mesh._color = color province.add(mesh); }) }) _this.map.add(province); }) }
geoJson
的坐標(biāo)需要進(jìn)行墨卡托投影轉(zhuǎn)換才能轉(zhuǎn)換成平面坐標(biāo),這里需要用到d3
// 墨卡托投影轉(zhuǎn)換 const projection = d3.geoMercator().center([104.0, 37.5]).scale(80).translate([0, 0]);
2.增加光照
我們把各種光都打上,環(huán)境光,半球光,點(diǎn)光,平行光。以平行光為例,增加投影,調(diào)整投影分辨率,避免投影出現(xiàn)馬賽克
const light = new THREE.DirectionalLight( 0xffffff, 0.5 ); light.position.set( 20, -50, 20 ); light.castShadow = true; light.shadow.mapSize.width = 1024; light.shadow.mapSize.height = 1024; this.scene.add(light);
castShadow = true
表示開(kāi)啟投影
3.增加陰影模糊
默認(rèn)的陰影沒(méi)有模糊效果,看起來(lái)像白熾燈照射的樣子,沒(méi)有柔和感。使用官方示例中的csm
來(lái)增加陰影模糊
import { CSM } from 'three/examples/jsm/csm/CSM.js'; this.csm = new CSM( { maxFar: params.far, cascades: 4, mode: params.mode, parent: this.scene, shadowMapSize: 1024, lightDirection: new THREE.Vector3( params.lightX, params.lightY, params.lightZ ).normalize(), camera: this.camera } );
4.增加鼠標(biāo)事件
在3d
空間中,鼠標(biāo)事件主要通過(guò)射線來(lái)獲取鼠標(biāo)所在位置,可以想象成鼠標(biāo)放出一道射線,照射到的第一個(gè)物體就是鼠標(biāo)所在位置。此時(shí)用的threejs
的Raycaster
,通過(guò)Raycaster
給對(duì)應(yīng)的省份增加鼠標(biāo)移入高亮效果和省份民懸浮展示效果
this.raycaster = new THREE.Raycaster(); // 傳入需要檢測(cè)的對(duì)象 group,group下的所有對(duì)象都會(huì)被檢測(cè)到,如果被射線照到,則intersects有值,表示鼠標(biāo)當(dāng)前在這些物體上 const intersects = this.raycaster.intersectObject( this.group, true ); // 代碼太多就不貼了,見(jiàn) GitHub源碼
5.渲染
threejs
的渲染一般調(diào)用原生的requestAnimationFrame
,主要做的事就是調(diào)用renderer
的render
方法,當(dāng)然因?yàn)槲覀冏隽岁幱澳:幚恚赃€有別的需要做的:
this.camera.updateMatrixWorld(); this.csm.update(); this.renderer.render(this.scene, this.camera);
6.動(dòng)畫(huà)效果
地圖上如果有一些動(dòng)畫(huà)效果,可以使用TWEEN.js
,github地址,比如地圖標(biāo)注的出現(xiàn)動(dòng)畫(huà):
最后再奉上項(xiàng)目地址
到此這篇關(guān)于基于Three.js制作一個(gè)3D中國(guó)地圖的文章就介紹到這了,更多相關(guān)Three.js 3D中國(guó)地圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
layui表格數(shù)據(jù)復(fù)選框回顯設(shè)置方法
今天小編就為大家分享一篇layui表格數(shù)據(jù)復(fù)選框回顯設(shè)置方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09JS實(shí)現(xiàn)動(dòng)態(tài)修改table及合并單元格的方法示例
這篇文章主要介紹了JS實(shí)現(xiàn)動(dòng)態(tài)修改table及合并單元格的方法,結(jié)合完整實(shí)例形式分析了JS動(dòng)態(tài)遍歷及修改table單元格的具體操作技巧,需要的朋友可以參考下2017-02-02js下拉選擇框與輸入框聯(lián)動(dòng)實(shí)現(xiàn)添加選中值到輸入框的方法
這篇文章主要介紹了js下拉選擇框與輸入框聯(lián)動(dòng)實(shí)現(xiàn)添加選中值到輸入框的方法,涉及javascript中onchange事件及頁(yè)面元素遍歷的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08JavaScript必知必會(huì)(十) call apply bind的用法說(shuō)明
這篇文章主要介紹了JavaScript必知必會(huì)(十) call apply bind的用法說(shuō)明 的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06Javascript操縱Cookie實(shí)現(xiàn)購(gòu)物車程序
Javascript操縱Cookie實(shí)現(xiàn)購(gòu)物車程序...2006-11-11IE Firefox 使用自定義標(biāo)簽的區(qū)別
IE Firefox 使用自定義標(biāo)簽的區(qū)別,需要的朋友可以參考下。2009-10-10DWR3 訪問(wèn)WEB元素的兩種方法實(shí)例詳解
這篇文章主要介紹了DWR3 訪問(wèn)WEB元素的兩種方法實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-01-01JS實(shí)現(xiàn)點(diǎn)擊網(wǎng)頁(yè)判斷是否安裝app并打開(kāi)否則跳轉(zhuǎn)app store
這篇文章主要介紹了JS實(shí)現(xiàn)點(diǎn)擊網(wǎng)頁(yè)判斷是否安裝app并打開(kāi)否則跳轉(zhuǎn)app store的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11