一、效果如下:

three.js + geojson 绘制广西地图

二、事先准备好要使用的数据

首先要准备好广西地图的geojson数据,可以通过阿里云的Data.GeoAtlas地理小工具获取想要的地理位置数据,我这里获取的是json文件。
three.js在使用时会受版本影响,我所使用的有效js文件:阿里云盘

三、使用geojson绘制地图

1、首先创建需要的div和设置样式

 <style>html body{width: 100%;height: 100%;margin:0;padding:0;overflow: hidden;}#backgroundImage{position: absolute;width: 100%;height: 100%;/*background: url("picture/bg.png") no-repeat center;*/z-index:-100;background-size: 100% 100%;}#cityInfo{position: absolute;background: white;padding: 10px;visibility: hidden;}</style><div id="container"></div><div id="cityInfo"></div>

2、js部分

(1)声明全局变量

    var scene,renderer,camera,light,control,map,controller,mesh;var group = new THREE.Group();var raycaster = new THREE.Raycaster();  //光线投射 用于进行鼠标拾取var mouse = new THREE.Vector2();var eventOffset = {};let currentSprite = null, currentSpriteTitle = '';var activeInstersect;var  cityInfo = document.getElementById('cityInfo');

(2)初始化场景相关

//初始化function init(){//渲染器renderer = new THREE.WebGLRenderer( { antialias: true } );renderer.setPixelRatio( window.devicePixelRatio );renderer.setSize( window.innerWidth, window.innerHeight );document.getElementById( 'container' ).appendChild( renderer.domElement );//场景scene = new THREE.Scene();//相机 透视相机camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000 );camera.position.set(0,10,200);camera.lookAt(scene.position);设置灯光 环境光var ambient = new THREE.AmbientLight(0x002bff, 0.8);scene.add(ambient);setController(); //设置控制loadMapData();initStarBackground();setRaycaster()setReSize();  //绑定浏览器缩放事件animate();}

设置控制器:

function setController(){controller = new THREE.OrbitControls(camera,renderer.domElement);//controls = new THREE.TrackballControls( camera, renderer.domElement );controller.minDistance = 20;controller.maxDistance = 5000;}

(3) 使用纹理贴图+点材质制作星空背景

function  initStarBackground(){const positions = [];const colors = [];const geometry = new THREE.BufferGeometry();for (var i = 0; i < 10000; i++) {var vertex = new THREE.Vector3();vertex.x = Math.random() * 2 - 1;vertex.y = Math.random() * 2 - 1;vertex.z = Math.random() * 2 - 1;positions.push(vertex.x, vertex.y, vertex.z);var color = new THREE.Color();color.setHSL(Math.random() * 0.2 + 0.5, 0.55, Math.random() * 0.25 + 0.55);colors.push(color.r, color.g, color.b);}geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));var textureLoader = new THREE.TextureLoader();var texture = textureLoader.load("picture/starball.png"); //加载纹理贴图var starsMaterial = new THREE.PointsMaterial({map: texture,size: 1,transparent: true,opacity: 1,vertexColors: true, //true:且该几何体的colors属性有值,则该粒子会舍弃第一个属性--color,而应用该几何体的colors属性的颜色//blending: AdditiveBlending,sizeAttenuation: true,});let stars = new THREE.Points(geometry, starsMaterial);stars.scale.set(300, 300, 300);scene.add(stars);}

(4)加载广西的geojson数据

function loadMapData(){//加载json文件let loader = new THREE.FileLoader();loader.load('./json/guangxi.json',function(data) {//将经纬坐标转化格式let jsonData = JSON.parse(data);initMap(jsonData);});}

(5) 绘制广西地图

在这里要注意:要使用墨卡托投影转换(d3)将经纬度转为坐标值。

 //创建一个空对象存放对象map = new THREE.Object3D();map.name = "广西";//墨卡托投影转换 将经纬度转为坐标值const projection = d3.geoMercator().center([108.320004,22.82402]).scale(80).translate([0,0]);guangxiJson.features.forEach((elem,index) => {//定义一个城市的3D对象const cityObj = new THREE.Object3D();//每个的 坐标 数组const coordinates = elem.geometry.coordinates;//循环坐标数组coordinates.forEach(multiPolygon =>{multiPolygon.forEach( polygon =>{const shape = new THREE.Shape();const  lineMaterial = new THREE.MeshBasicMaterial({color:0xffffff})const lineGeometry = new THREE.Geometry();for(let i = 0; i< polygon.length; i++){const [x,y] = projection(polygon[i]);if(i === 0){shape.moveTo(x,-y);}shape.lineTo(x,-y);lineGeometry.vertices.push(new THREE.Vector3(x,-y,0.55));}//拉伸厚度const extrudeSettings = {depth:0.5,bevelEnabled:false};const geometry = new THREE.ExtrudeGeometry(shape,extrudeSettings);const material = new THREE.MeshPhongMaterial({color:'#637585',// transparent:true,// opacity:0.9,alphaMap: 0x000000});const material1 = new THREE.MeshPhongMaterial({color:'#637585',// transparent:true,// opacity:0.9,alphaMap: 0x000000});mesh = new THREE.Mesh(geometry,[material,material1]);const line = new THREE.Line(lineGeometry,lineMaterial);cityObj.add(mesh);cityObj.add(line);})})//将geo的属性放到城市模型中cityObj.properties = elem.properties;// console.log(cityObj.properties.centroid)if(cityObj.properties.centroid){const [ x,y] = projection(cityObj.properties.centroid);cityObj.properties._centroid =[x,y];var city = document.createElement('div');city.className=cityObj.properties.name;city.style.backgroundColor = ' #32C0F1';city.style.position = 'absolute';city.textContent = cityObj.properties.name;var cityLabel = new THREE.CSS2DObject(city);cityLabel.position.set(cityObj.properties.centroid[0] - window.innerWidth /2,cityObj.properties.centroid[1],0)cityObj.add(cityLabel);console.log(cityLabel);}map.add(cityObj);map.scale.set(13,13,13);})group.add(map);map.position.z = 0map.rotateX(-Math.PI / 4);scene.add(group);

(6) 鼠标移动,光射线相交的地方,显示对应的城市名标签

a. 城市的信息
 function createProvinceInfo(){//console.log(activeInstersect);if(activeInstersect.length !== 0 && activeInstersect[0].object.parent.properties.name){var properties = activeInstersect[0].object.parent.properties;cityInfo.textContent = properties.name;cityInfo.style.visibility = 'visible';}else{cityInfo.style.visibility = 'hidden';}}
b. 最主要是处理 鼠标与摄像机的位置来更新射线,这里用到了鼠标拾取也就是 THREE.Raycaster()

光照射线,捕获与光线相交的物体(鼠标移动代表光束移动)

function setRaycaster(){function onMouseMove(event){// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)mouse.x = (event.clientX / window.innerWidth ) * 2 -1;mouse.y = -(event.clientY / window.innerHeight) * 2 +1;eventOffset.x = event.clientX;eventOffset.y = event.clientY;cityInfo.style.left = eventOffset.x + 2 + 'px';cityInfo.style.top = eventOffset.y + 2 + 'px';}window.addEventListener('mousemove', onMouseMove,false);}

在鼠标移动时,要实时更新鼠标选中的部位的颜色,鼠标离开自然也要恢复颜色,因此要在动画中做更新。

function animate(){// 通过摄像机和鼠标位置更新射线raycaster.setFromCamera(mouse,camera);// 计算物体和射线的焦点// 传入需要检测的对象 this.scene.children,this.scene.children下的所有对象都会被检测到,如果被射线照到,则intersects有值,表示鼠标当前在这些物体上let intersects = raycaster.intersectObjects(scene.children, true);if(activeInstersect && activeInstersect.length > 0) //将上一次选中的恢复颜色{activeInstersect.forEach(elem =>{elem.object.material[0].color.set('#637585');elem.object.material[1].color.set('#637585');});}activeInstersect = []  //设置为空for(var i = 0; i < intersects.length;i++){if(intersects[i].object.material && intersects[i].object.material.length === 2){activeInstersect.push(intersects[i]);intersects[i].object.material[0].color.set('#F1C232');intersects[i].object.material[1].color.set('#F1C232');break;  //只取一个}}createProvinceInfo();requestAnimationFrame(animate);// this.cube.rotation.x += 0.05;// this.cube.rotation.y += 0.05;renderer.render(scene,camera);//labelRenderer.render(scene,camera);// group.rotateZ(0.05);}

使用three.js + geojson 完成广西地图的绘制(上篇)相关推荐

  1. Android中使用WebChromeClient显示Openlayers加载本地GeoJson文件显示地图(跨域问题解决)

    场景 Openlayers中加载GeoJson文件显示地图: Openlayers中加载GeoJson文件显示地图_BADAO_LIUMANG_QIZHI的博客-CSDN博客 上面加载显示GeoJso ...

  2. Openlayers中加载GeoJson文件显示地图

    场景 Openlayers下载与加载geoserver的wms服务显示地图: Openlayers下载与加载geoserver的wms服务显示地图_BADAO_LIUMANG_QIZHI的博客-CSD ...

  3. 广西地图html插件,ECharts绘制中国地图、广西地图

    准备工作:导入ECharts依赖.和地图需要的.js文件. 文件获取方式: 官网:url github:url (下载完后 :incubator-echarts-4.8.0mapjsprovince目 ...

  4. 视频教程-Threejs GeoJSON离线3D地图-JavaScript

    Threejs GeoJSON离线3D地图 以特邀嘉宾身份参加多起大型web前端技术分享会,5年纯前端经验,多个大型web项目经验,JS全栈工程师,现任一家大数据公司任web前端部门经理.开源项目MT ...

  5. JS 如何调用高德地图

    最近配合后台做管理系统,需要前端用原生html页面嵌入到后台,于是乎...记录下原生JS怎么使用高德地图吧 一.获取高德地图的key 获取地址:高德开放平台https://lbs.amap.com/ ...

  6. js百度地图鼠标绘制工具条库

    本篇文章是介绍百度地图鼠标绘制工具条库基本使用 百度地图的覆盖物的编辑类参考:[鼠标绘制工具条库](http://api.map.baidu.com/library/DrawingManager/1. ...

  7. 【Pyecharts50例】添加自定义地图/geojson使用/区县地图

    前言 Pyecharts支持最小粒度到城市级别的数据,但如果想画某个城市各区的地图,就没办法直接使用了. 这里提供一个网站,是阿里开源的,最小粒度到区县界别http://datav.aliyun.co ...

  8. java echarts 散点图,echarts在地图上绘制散点图(任意点)

    项目需求:在省份地图上绘制散点图,散点位置不一定是哪个城市或哪个区县,即任意点 通过查询官网文档,找到一个与需求类似的Demo:https://www.echartsjs.com/gallery/ed ...

  9. 在Arcgis地图上绘制Echarts热力图(Heatmap)

    在Arcgis地图上绘制Echarts热力图(Heatmap) 2018-08-30 10:18 [原创]本文地址:https://www.cnblogs.com/qiaoge0923/p/95623 ...

最新文章

  1. 利用OpenCV+ConvNets检测几何图形
  2. python学习总目录
  3. Android HAL层与Linux Kernel层驱动开发简介
  4. 统一并发 IV——走向跨平台
  5. #436. 子串的最大差(单调栈)
  6. 转帖:Three Ways to Inject Your Code into Another Process
  7. 中国电信联合多方加速推进OpenStack技术产业化 —— OSCAR即将发布“OpenStack技术应用场景”技术规范...
  8. 直击备份恢复的痛点:基于 TiDB Binlog 的快速时间点恢复
  9. 前端,后端,前台,后台到底应该怎么理解。
  10. Words Reciting 2016.5.4
  11. Learn Git Branching 学习笔记(Git 技术、技巧与贴士集合篇)
  12. Javascript实现手机发送验证码
  13. 谷歌浏览器点击上传文件崩溃/上传图片崩溃/打开浏览文件未响应 解决方案
  14. windows10正式版官方原版镜像iso下载地址
  15. 四层交换机实现负载均衡
  16. Invalid format specifier的解决方法
  17. pico的学习之路(四)——HC-SR501人体感应模块(树莓派pico实现)
  18. 【应用层】DNS协议
  19. proxy代理的配置
  20. ICP网站备案查询系统php版 v1.0

热门文章

  1. 【操作系统】第五章——虚拟内存技术
  2. Python print 玩转点阵字
  3. 面向企业级的开源WebGIS解决方案--MapGuide(安装)
  4. 三分钟,如何说好自我介绍?
  5. 管理计算机 ppt,PowerPoint(PPT) 2016
  6. js垃圾回收机制,内存泄露和内存溢出,解决闭包产生的内存泄露详解
  7. CENTOS: 安装memSQL
  8. HTTP抓包神器---Fiddler
  9. 荣联科技再出发,奏响集成商转型最强音
  10. Matlab 实现图像的直角坐标系和极坐标系的相互转化