首页 > Python资料 博客日记
Threejs 实现3D 地图(02)创建3d 地图
2024-10-20 01:00:08Python资料围观34次
文章Threejs 实现3D 地图(02)创建3d 地图分享给大家,欢迎收藏Python资料网,专注分享技术知识
"d3": "^7.9.0",
"three": "^0.169.0",
"vue": "^3.5.10"
地图数据来源: DataV.GeoAtlas地理小工具系列
<script setup>
import {onMounted, ref} from 'vue'
import * as THREE from 'three'
import * as d3 from "d3"; //莫开托坐标 矫正地图坐标
import map from './constant/map.json'
// 引入轨道控制器扩展库OrbitControls.js
import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
// 拿到页面的宽高
const width = window.innerWidth, height = window.innerHeight;
// d3投影转换函数 (109, 34.5 中心点位置)
const handleProject = d3.geoMercator().center([109, 34.5]).scale(1000).translate([0, 0])
// 存储地图容器
const mapContainer = new THREE.Object3D()
// 创建场景
const scene = new THREE.Scene();
// 将背景颜色设置为白色
scene.background = new THREE.Color("#000000");
// 创建相机
const camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 10000);
// 设置相机位置
camera.position.z = 1000;
// // 辅助线 AxesHelper
const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(width, height);
// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
//阻尼 更真实
controls.enableDamping = true
// 地图数据处理
const initGeom = () => {
// 将地图数据显示在屏幕上
// 如果是服务器返回的数据,需要先将数据转为geojson格式 这里默认用的本地数据
handleData(map)
}
const handleData = (jsonData) => {
const featureList = jsonData.features;
featureList.forEach((feature) => {
// 创建省的容器
const province = new THREE.Object3D;
// 省份名称
province.properties = feature.properties.name
province.name = feature.properties.name // 省份名称
mapContainer.name = feature.properties.name // 省份名称
// 省份坐标信息
const coordinates = feature.geometry.coordinates
if (feature.geometry.type === 'MultiPolygon') {
coordinates.forEach((cord) => {
// coordinate 就是边界素组坐标系
cord.forEach((coordinate) => {
// 三维多边形
const extrudeMesh = creatDepthPolygon(coordinate)
// 给extrudeMesh对象加一个自定义的属性(properties)用来存放省份名称
extrudeMesh.properties = feature.properties.name
// 绘制省份边缘线条
const line = createLine(coordinate);
// 将面加入3d 中
province.add(extrudeMesh)
// 将线加入3d 中
province.add(line)
})
})
}
if (feature.geometry.type === 'Polygon') {
coordinates.forEach((coordinate) => {
// 三维多边形
const extrudeMesh = creatDepthPolygon(coordinate)
extrudeMesh.properties = feature.properties.name
// 线条
const line = createLine(coordinate);
province.add(extrudeMesh)
province.add(line)
})
}
// 将每个省份的容器加入到地图容器中
mapContainer.add(province)
})
// 将地图容器加入到场景中
scene.add(mapContainer)
}
// 创建三维多边形(也就是每个省份的地图)
const creatDepthPolygon = (coordinate) => {
const shape = new THREE.Shape();
// 每一个item都是省份边界坐标 需要把 json 的坐标系 转化为d3的坐标系 例如:[117.429915,40.576141]
coordinate.forEach((item, index) => {
const [x_XYZ, y_XYZ] = handleProject(item)
if (index === 0) {
// moveTo 的主要作用是定义形状的起点位置
shape.moveTo(x_XYZ, -y_XYZ)
} else {
// 依次按照坐标 形成一个多边形
shape.lineTo(x_XYZ, -y_XYZ)
}
})
const extrudeSettings = {
steps: 2,
depth: 16,
bevelEnabled: true,
bevelThickness: 1,
bevelSize: 1,
bevelOffset: 0,
bevelSegments: 1
};
// ExtrudeGeometry 创建一个多边形
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings) //挤压缓冲几何体
// 设置每个身份的背景颜色
const material = new THREE.MeshBasicMaterial({
// color: new THREE.Color(Math.random() * 0xffffff), // 每个省随机赋色
color: '#d13a34',
transparent: true,
opacity: 0.6
})
return new THREE.Mesh(geometry, material)
}
// 创建省份边界线条
const createLine = (coordinate) => {
const material = new THREE.LineBasicMaterial({
color: '#ffffff'
});
const points = []
coordinate.forEach((item, index) => {
// 每一个item都是省份边界坐标 需要把 json 的坐标系 转化为d3的坐标系 例如:[117.429915,40.576141]
const [x_XYZ, y_XYZ] = handleProject(item)
points.push(new THREE.Vector3(x_XYZ, -y_XYZ, 25))
})
const geometry = new THREE.BufferGeometry().setFromPoints(points);
return new THREE.Line(geometry, material);
}
// 渲染页面
const render = () => {
// 将场景(scene)和摄像机(camera 加入进来)
renderer.render(scene, camera)
// 渲染下一帧的时候会调用render函数
requestAnimationFrame(render)
controls.update()
}
const initLight = () => {
// 基本光源
const ambLight = new THREE.AmbientLight('#ffffff', 0.3)
/**
* 设置聚光灯相关的的属性
*/
const spotLight = new THREE.SpotLight(0xFFFFFF); // 聚光灯
spotLight.position.set(40, 200, 10);
spotLight.castShadow = true; // 只有该属性为true时,该点光源允许产生阴影,并且下列属性可用
scene.add(ambLight, spotLight); // 向场景中添加光源
}
onMounted(() => {
// 添加物体到场景
initGeom()
// 渲染
render()
// 设置环境光
initLight()
// 将渲染加入到页面上
document.body.appendChild(renderer.domElement);
})
</script>
<template>
<div id="info"></div>
</template>
<style scoped>
</style>
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
上一篇:第四章,使用jQuery处理Ajax
下一篇:【图论】Dijkstra
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Python与PyTorch的版本对应
- Anaconda版本和Python版本对应关系(持续更新...)
- Python pyinstaller打包exe最完整教程
- Could not build wheels for llama-cpp-python, which is required to install pyproject.toml-based proj