这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

不想看繁琐步骤的,可以直接去github下载项目,如果可以顺便来个star哈哈

本项目使用vue-cli创建,但不影响使用,主要绘制都已封装成类

1、使用geoJson绘制3d地图

1.1 创建场景相关

// 创建webGL渲染器
this.renderer = new THREE.WebGLRenderer( { antialias: true,alpha: true} );
this.renderer.shadowMap.enabled = true; // 开启阴影
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
this.renderer.toneMappingExposure = 1.25; // 根据自己的需要调整颜色模式
// 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); // 场景
this.scene = new THREE.Scene();
this.scene.background = null
// 相机 透视相机
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 根据json绘制地图

利用THREE.Shape绘制地图的平面边数据,再用THREE.ExtrudeGeometry将一个面拉高成3d模型,3d饼图同理也可以这么制作

let jsonData = require('./json/china.json')
this.initMap(jsonData); // initMap 方法主要部分
initMap(chinaJson) {
/* ...省略
...
*/
chinaJson.features.forEach((elem, index) => {
// 定一个省份3D对象
const province = new THREE.Object3D();
// 每个的 坐标 数组
const { coordinates } = elem.geometry;
const color = COLOR_ARR[index % COLOR_ARR.length]
// 循环坐标数组
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); // 平面部分材质
const material = new THREE.MeshStandardMaterial( {
metalness: 1,
color: color, } );
// 拉高部分材质
const material1 = new THREE.MeshStandardMaterial( {
metalness: 1,
roughness: 1,
color: color, } ); const mesh = new THREE.Mesh(geometry, [
material,
material1
]);
// 设置高度将省区分开来
if (index % 2 === 0) {
mesh.scale.set(1, 1, 1.2);
}
// 给mesh开启阴影
mesh.castShadow = true
mesh.receiveShadow = true
mesh._color = color
province.add(mesh); }) }) _this.map.add(province); })
}

geoJson的坐标需要进行墨卡托投影转换才能转换成平面坐标,这里需要用到d3

// 墨卡托投影转换
const projection = d3.geoMercator().center([104.0, 37.5]).scale(80).translate([0, 0]);

2、增加光照

我们把各种光都打上,环境光,半球光,点光,平行光。以平行光为例,增加投影,调整投影分辨率,避免投影出现马赛克

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表示开启投影

3、增加阴影模糊

默认的阴影没有模糊效果,看起来像白炽灯照射的样子,没有柔和感。使用官方示例中的csm来增加阴影模糊

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、增加鼠标事件

3d空间中,鼠标事件主要通过射线来获取鼠标所在位置,可以想象成鼠标放出一道射线,照射到的第一个物体就是鼠标所在位置。此时用的threejsRaycaster,通过Raycaster给对应的省份增加鼠标移入高亮效果和省份民悬浮展示效果

this.raycaster = new THREE.Raycaster();
// 传入需要检测的对象 group,group下的所有对象都会被检测到,如果被射线照到,则intersects有值,表示鼠标当前在这些物体上
const intersects = this.raycaster.intersectObject( this.group, true );
// 代码太多就不贴了,见 GitHub源码

5、渲染

threejs的渲染一般调用原生的requestAnimationFrame,主要做的事就是调用rendererrender方法,当然因为我们做了阴影模糊处理,所以还有别的需要做的:

this.camera.updateMatrixWorld();
this.csm.update();
this.renderer.render(this.scene, this.camera);

6、动画效果

地图上如果有一些动画效果,可以使用TWEEN.jsgithub地址,比如地图标注的出现动画:

最后再奉上项目地址

本文转载于:

https://juejin.cn/post/7057808453263163422

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--可视化大屏-用threejs撸一个3d中国地图的更多相关文章

  1. 可视化大屏的终极解决方案居然这么简单,vue-autofit一行全搞定!

    可视化大屏适配/自适应现状 可视化大屏的适配是一个老生常谈的话题了,现在其实不乏一些大佬开源的自适应插件.工具但是我为什么还要重复造轮子呢?因为目前市面上适配工具每一个都无法做到完美的效果,做出来的东 ...

  2. 使用DataV制作实时销售数据可视化大屏(实验篇)

    课时1:背景介绍 任务说明 ABC是一家销售公司,其客户可以通过网站下单订购该公司经营范围内的商品,并使用信用卡.银行卡.转账等方式付费.付费成功后,ABC公司会根据客户地址依据就近原则选择自己的货仓 ...

  3. Qt编写数据可视化大屏界面电子看板系统

    一.前言 目前大屏大数据可视化UI这块非常火,趁热也用Qt来实现一个,Qt这个一站式超大型GUI超市,没有什么他做不了的,大屏电子看板当然也不在话下,有了QSS和QPainter这两个无敌的工具组合, ...

  4. Qt编写数据可视化大屏界面电子看板13-基础版

    一.前言 之前发布的Qt编写的可视化大屏电子看板系统,很多开发者比较感兴趣,也收到了很多反馈意见,纵观市面上的大屏系统,基本上都是B/S结构的web版本,需要在后台进行自定义配置模块,绑定数据源等,其 ...

  5. Qt编写数据可视化大屏界面电子看板12-数据库采集

    一.前言 数据采集是整个数据可视化大屏界面电子看板系统核心功能,没有数据源,这仅仅是个玩具UI,没啥用,当然默认做了定时器模拟数据,产生随机数据,这个可以直接配置文件修改来选择采用何种数据采集方法,总 ...

  6. Qt编写数据可视化大屏界面电子看板11-自定义控件

    一.前言 说到自定义控件,我是感觉特别熟悉的几个字,本人亲自原创的自定义控件超过110个,都是来自各个行业的具体应用真实需求,而不是凭空捏造的,当然有几个小控件也有点凑数的嫌疑,在编写整个数据可视化大 ...

  7. Qt编写数据可视化大屏界面电子看板9-曲线效果

    一.前言 为了编写数据可视化大屏界面电子看板系统,为了能够兼容Qt4和嵌入式linux系统,尤其是那种主频很低的,但是老板又需要在这种硬件上(比如树莓派.香橙派.全志H3.imx6)展示这么华丽的界面 ...

  8. Qt编写数据可视化大屏界面电子看板8-调整间距

    一.前言 在数据可视化大屏界面电子看板系统中,前期为了使用目标客户机,调整间距是必不可少的工作,QMainWindow中的QDockWidget,会默认生成布局和QSplitter调整宽高大小,鼠标移 ...

  9. Qt编写数据可视化大屏界面电子看板5-恢复布局

    一.前言 恢复布局这个功能在整个数据可视化大屏界面电子看板系统中非常有用,很多时候不小心把现有布局拖动乱了,(当然如果不想布局被拖动改动,可以修改配置文件中的MoveEnable参数来控制,默认为真表 ...

  10. Qt编写数据可视化大屏界面电子看板4-布局另存

    一.前言 布局另存是数据可视化大屏界面电子看板系统中的额外功能之一,主要用于有时候用户需要在现有布局上做个微调,然后直接将该布局另存为一个布局配置文件使用,可以省略重新新建布局重新来一次大的调整的工作 ...

随机推荐

  1. JS Leetcode 1370. 上升下降字符串 题解分析,桶排序与charCodeAt fromCharCode妙用

    壹 ❀ 引 本题来自LeetCode1370. 上升下降字符串,难度简单,是一道考察对于字符串遍历熟练度的题目,题目描述如下: 给你一个字符串 s ,请你根据下面的算法重新构造字符串: 从 s 中选出 ...

  2. Sunnyui画曲线溢出错误

    之前用sunnyui做展示数据库数据曲线的时候.偶然会报溢出错误,也不报错错误在哪,就是直接程序都跑不动了. 后面发现 设置曲线上下限的时候,当上下限一样的时候就会导致溢出错误.sunnyui的曲线也 ...

  3. NC24370 [USACO 2012 Dec S]Milk Routing

    题目链接 题目 题目描述 Farmer John's farm has an outdated network of M pipes (1 <= M <= 500) for pumping ...

  4. 计算机算法设计与分析(第5版)PDF

    <计算机算法设计与分析(第5版)>是2018年电子工业出版社出版的图书,作者是王晓东. 整本书的结构是:先介绍算法设计策略思想,然后从解决经典算法问题来学习,通过实践的方式去学习算法. 网 ...

  5. Centos8 安装 MySQL8.0.26

    下载 访问 https://dev.mysql.com/downloads/mysql/ 选择 Red Hat Enterprise Linux / Oracle Linux 选择 Red Hat E ...

  6. Wireguard笔记(一) 节点安装配置和参数说明

    目录 Wireguard笔记(一) 节点安装配置和参数说明 Wireguard笔记(二) 命令行操作 Wireguard笔记(三) lan-to-lan子网穿透和多网段并存 简介 虚拟子网软件,类似于 ...

  7. 【Unity3D】相机

    1 简介 ​ 相机用于渲染游戏对象,每个场景中可以有多个相机,每个相机独立成像,每个成像都是一个图层,最后渲染的图层在最前面显示. ​ 相机的属性面板如下: Clear Flags:设置清屏颜色,Sk ...

  8. win32 - 将文件的访问权限给特定的用户

    需要首先获取特定用户的SID. 这是一些步骤, 验证输入参数. 为可能足够大的SID和域名创建缓冲区. 在循环中,调用LookupAccountName以检索提供的帐户名的SID.如果SID的缓冲区或 ...

  9. day03--vi和vim快捷方式及操作系统目录介绍

    1.编辑命令vi vim是vi的增强版 提高编程的效率 1.vi命令模式信息 命令模式: 可实现很多特殊功能操作 不能输入任何内容 编辑模式: 可编辑内容信息 底行模式:可以输入特殊的命令信息 wq保 ...

  10. django1.11和django2.2中namespace的用法

    django1.11中namespace用法 urlpatterns = [ url(r'^user/', include('user.urls', namespace='user')) ] djan ...