参考资料
- 正投影相机
- ...
- 相机控件MapControls
知识点
注:基于Three.jsv0.155.0
- 正投影相机
- 正投影相机-Canvas尺寸变化
- 包围盒Box3
- 地图案例(包围盒、正投影)
- 相机动画(.position和.lookAt())
- 不同方向的投影视图
- 旋转渲染结果(.up相机上方向)
- 管道漫游案例
- OrbitControls旋转缩放限制
- 相机控件MapControls
代码实现
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js</title>
</head>
<body>
</body>
<!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 -->
<script type="importmap">
{
"imports": {
"three": "./js/three.module.js",
"three/addons/": "../three.js/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { MapControls } from 'three/addons/controls/MapControls.js';
const width = window.innerWidth
const height = window.innerHeight
// 场景
const scene = new THREE.Scene();
const data = [
[110.3906, 34.585],
[110.8301, 34.6289],
[111.1816, 34.8047],
[111.5332, 34.8486],
[111.7969, 35.0684],
[112.0605, 35.0684],
[112.0605, 35.2881],
[112.7637, 35.2002],
[113.1152, 35.332],
[113.6426, 35.6836],
[113.7305, 36.3428],
[114.873, 36.123],
[114.9609, 36.0791],
[115.1367, 36.2109],
[115.3125, 36.0791],
[115.4883, 36.167],
[115.3125, 35.8154],
[116.1035, 36.0791],
[115.4883, 35.7275],
[115.2246, 35.4199],
[115.0488, 35.376],
[114.7852, 35.0684],
[115.4004, 34.8486],
[115.5762, 34.585],
[116.1914, 34.585],
[116.1914, 34.4092],
[116.543, 34.2773],
[116.6309, 33.9258],
[116.1914, 33.7061],
[116.0156, 33.9697],
[115.6641, 34.0576],
[115.5762, 33.9258],
[115.5762, 33.6621],
[115.4004, 33.5303],
[115.3125, 33.1787],
[114.873, 33.1348],
[114.873, 33.0029],
[115.1367, 32.8711],
[115.2246, 32.6074],
[115.5762, 32.4316],
[115.8398, 32.5195],
[115.9277, 31.7725],
[115.4883, 31.6846],
[115.4004, 31.4209],
[115.2246, 31.4209],
[115.1367, 31.5967],
[114.7852, 31.4648],
[114.6094, 31.5527],
[114.5215, 31.7725],
[114.1699, 31.8604],
[113.9941, 31.7725],
[113.8184, 31.8604],
[113.7305, 32.4316],
[113.4668, 32.2998],
[113.2031, 32.4316],
[112.3242, 32.3438],
[111.5332, 32.6074],
[111.0059, 33.2666],
[111.0059, 33.5303],
[110.6543, 33.8379],
[110.6543, 34.1455],
[110.4785, 34.2334],
[110.3906, 34.585]
]
const pointsArr = [];// 一组二维向量表示一个多边形轮廓坐标
data.forEach(function(e){
// data坐标数据转化为Vector2构成的顶点数组
const v2 = new THREE.Vector2(e[0],e[1])
pointsArr.push(v2);
})
// Shape表示一个平面多边形轮廓,参数是二维向量构成的数组pointsArr
const shape = new THREE.Shape(pointsArr);
// 多边形shape轮廓作为ShapeGeometry参数,生成一个多边形平面几何体
const geometry = new THREE.ShapeGeometry(shape);
// 生成一个平面网格模型
const mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
color: '#0000ff',
side: THREE.DoubleSide
}))
// 设置模型位置
mesh.position.set(0, 0, 0);
// 添加模型到场景
scene.add(mesh);
// 点光源
const pointLight = new THREE.PointLight( 0xffffff, 1.0, 0, 0);
pointLight.position.set(200, 200, 200 );
scene.add( pointLight );
// 环境光
const ambientLight = new THREE.AmbientLight( 0xffffff, 1);
scene.add( ambientLight );
// 坐标系
const axes = new THREE.AxesHelper(200);
scene.add(axes);
// 相机
const s = 2.5;//控制left, right, top, bottom范围大小
const k = width / height; //canvas画布宽高比
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 8000);
// const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 3000);
// camera.position.set(300, 300, 300);
// camera.lookAt(0, 0, 0); //指向坐标原点
// 包围盒计算模型对象的大小和位置
const box3 = new THREE.Box3();
box3.expandByObject(mesh); // 计算模型包围盒
const size = new THREE.Vector3();
box3.getSize(size); // 计算包围盒尺寸
console.log('模型包围盒尺寸',size);
const center = new THREE.Vector3();
box3.getCenter(center); // 计算包围盒中心坐标
console.log('模型中心坐标1',center);
const x = 113.51,y = 33.88;
camera.position.set(x, y, 300);
// 你可以看到模型相比原来上下颠倒 y坐标轴朝下
camera.up.set(0,-1,0)
camera.lookAt(x, y, 0);
// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.render(scene, camera);
document.body.appendChild(renderer.domElement);
renderer.outputColorSpace = THREE.SRGBColorSpace;//设置为SRGB颜色空间
// const controls = new OrbitControls(camera, renderer.domElement);
// controls.target.set(x, y, 0); //与lookAt参数保持一致
// controls.update();//update()函数内会执行camera.lookAt(controls.target)
// // 左右旋转范围
// controls.minAzimuthAngle = -Math.PI/2;
// controls.maxAzimuthAngle = Math.PI/2;
// // Vector3 {x: -49.803731395661714, y: 146.90160246353028, z: 35.47368304973255}
// // Vector3 {x: -11.970638355445846, y: -51.0801205834488, z: 0.7429414745816755}
// // 渲染循环
// let angle = 0; //用于圆周运动计算的角度值
// const R = 100; //相机圆周运动的半径
// function render() {
// angle += 0.01;
// // 相机y坐标不变,在XOZ平面上做圆周运动
// camera.position.x = R * Math.cos(angle);
// camera.position.z = R * Math.sin(angle);
// renderer.render(scene, camera);
// camera.lookAt(0,0,0);
// // console.log('🚀 ~ file: 6.加载外部三维模型.html:70 ~ render ~ camera:', camera.position) // 鼠标左键改变相机位置
// // console.log('🚀 ~ file: 6.加载外部三维模型.html:66 ~ controls:', controls.target) // 鼠标右键改变相机观察点
// requestAnimationFrame(render);
// }
// // render();
// 控制器
// controls.addEventListener('change', () => {
// // 因为动画渲染了,所以这里可以省略
// renderer.render(scene, camera);
// });
const controls = new MapControls(camera, renderer.domElement);
controls.addEventListener('change', function () {
// 鼠标右键旋转时候,查看.position变化
// 鼠标左键拖动的时候,查看.position、.target的位置会变化
console.log('camera.position',camera.position);
console.log('controls.target',controls.target);
});
</script>
</html>