携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情
最近在学习Three.js,纯粹的示例程序过于乏味,让人昏昏欲睡。用自己掌握的知识做一些自己感兴趣的、喜爱的小东西。巩固学到的知识的同时也愉悦了身心。
今天用Three.js做了个相册魔方,每个面上放上自己宝贝(大宝贝、小宝贝都可以哦)的照片,很炫哦。
前置条件
在自己的电脑上安装了Nginx,使用Nginx作为静态资源服务器。
本篇文章中使用的图片的浏览地址是:http://localhost:8000/momo.png。
示例程序的基本骨架
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>相册魔方</title>
<script src="https://cdn.bootcdn.net/ajax/libs/three.js/r99/three.min.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<!-- three.js代码 -->
<script>
// ...
</script>
</body>
</html>
说明:
- 引入 Three.js 函数库;
- 定义了一个
id为container的div元素,用于存放内容; - 将
body的margin设置成0; <script>标签用于存放示例程序JS代码。
操作步骤
- 定义一个
init()方法,在页面加载成功后调用。
/**
* 初始化方法
*/
function init() {
// ...
}
window.onload = init;
示例程序所有相关的业务代码都放存了init()方法体中。
- 定义 Three.js 三大件:场景、摄像机、渲染器。
// 场景
var scene = new THREE.Scene();
// 透视摄像机
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 渲染器
var renderer = new THREE.WebGLRenderer({ antialias: true });
// 设置摄像机的位置
camera.position.z = 600;
// 设置渲染器背景颜色
renderer.setClearColor("#222222");
// 设置渲染器大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染的结果输出到指定页面元素中
document.getElementById("container").appendChild(renderer.domElement);
这里定义了场景、摄像机、渲染器,并且设置了摄像机的位置、渲染器背景颜色、渲染器大小,最后将渲染的结果输出到container页面元素中。
摄像机的位置也会影响立方体的显示大小,设置不合适的话,立方体会显示不出来。
- 给
window添加resize事件,当窗体大小变化时,立体体大小也会随着变化。
window.addEventListener( 'resize', () => {
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width, height);
// 摄像机视锥体长宽比
camera.aspect = width / height;
// 更新摄像机投影矩阵
camera.updateProjectionMatrix();
});
Camera.updateProjectionMatrix():更新摄像机投影矩阵。在任何参数被改变以后必须被调用。
- 定义立方体,六个面都加载图片
var image_1 = new THREE.TextureLoader().load( 'http://localhost:8000/momo.png' );
var image_2 = new THREE.TextureLoader().load( 'http://localhost:8000/momo.png' );
var image_3 = new THREE.TextureLoader().load( 'http://localhost:8000/momo.png' );
var image_4 = new THREE.TextureLoader().load( 'http://localhost:8000/momo.png' );
var image_5 = new THREE.TextureLoader().load( 'http://localhost:8000/momo.png' );
var image_6 = new THREE.TextureLoader().load( 'http://localhost:8000/momo.png' );
var material_1 = new THREE.MeshBasicMaterial( { map: image_1 } );
var material_2 = new THREE.MeshBasicMaterial( { map: image_2 } );
var material_3 = new THREE.MeshBasicMaterial( { map: image_3 } );
var material_4 = new THREE.MeshBasicMaterial( { map: image_4 } );
var material_5 = new THREE.MeshBasicMaterial( { map: image_5 } );
var material_6 = new THREE.MeshBasicMaterial( { map: image_6 } );
var materials = [];
materials.push(material_1);
materials.push(material_2);
materials.push(material_3);
materials.push(material_4);
materials.push(material_5);
materials.push(material_6);
// 创建一个立方体
var cubeGeometry = new THREE.BoxGeometry(300, 300, 300);
var cube = new THREE.Mesh(cubeGeometry, materials);
//将立方体添加到场景中
scene.add(cube);
这里六个面我使用的是一个图片,如果有需求,可以自行修改每个面的图片。
TextureLoader:加载texture的一个类。 内部使用ImageLoader来加载文件。
- 添加光源
// 环境光
var ambientLight = new THREE.AmbientLight( 0xffffff, 0.2);
scene.add( ambientLight );
// 点光源
var pointLight = new THREE.PointLight( 0xffffff, 1 );
pointLight.position.set( 325, 350, 325 );
scene.add( pointLight );
AmbientLight:环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。
PointLight:从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光。该光源可以投射阴影。
- 使立方体转起来
function animate() {
requestAnimationFrame( animate )
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera )
}
animate();
到这里,照片魔方就做出来了。
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>相册魔方</title>
<script src="https://cdn.bootcdn.net/ajax/libs/three.js/r99/three.min.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<!-- three.js代码 -->
<script>
/**
* 初始化方法
*/
function init() {
// 场景
var scene = new THREE.Scene();
// 透视摄像机
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 渲染器
var renderer = new THREE.WebGLRenderer({ antialias: true });
// 设置摄像机的位置
camera.position.z = 600;
// 设置渲染器背景颜色
renderer.setClearColor("#222222");
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染的结果输出到指定页面元素中
document.getElementById("container").appendChild(renderer.domElement);
window.addEventListener( 'resize', () => {
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
var image_1 = new THREE.TextureLoader().load( 'https://cdn.pixabay.com/photo/2018/01/13/19/39/fashion-3080644__340.jpg' );
var image_2 = new THREE.TextureLoader().load( 'https://cdn.pixabay.com/photo/2018/01/05/07/05/people-3062246__340.jpg' );
var image_3 = new THREE.TextureLoader().load( 'https://cdn.pixabay.com/photo/2015/12/17/22/26/portrait-1097950__340.jpg' );
var image_4 = new THREE.TextureLoader().load( 'https://cdn.pixabay.com/photo/2018/01/18/01/44/beautiful-3089385__340.jpg' );
var image_5 = new THREE.TextureLoader().load( 'https://cdn.pixabay.com/photo/2015/03/28/00/39/woman-695456_960_720.jpg' );
var image_6 = new THREE.TextureLoader().load( 'https://cdn.pixabay.com/photo/2015/03/04/19/41/woman-659350__340.jpg' );
var material_1 = new THREE.MeshBasicMaterial( { map: image_1 } );
var material_2 = new THREE.MeshBasicMaterial( { map: image_2 } );
var material_3 = new THREE.MeshBasicMaterial( { map: image_3 } );
var material_4 = new THREE.MeshBasicMaterial( { map: image_4 } );
var material_5 = new THREE.MeshBasicMaterial( { map: image_5 } );
var material_6 = new THREE.MeshBasicMaterial( { map: image_6 } );
var materials = [];
materials.push(material_1);
materials.push(material_2);
materials.push(material_3);
materials.push(material_4);
materials.push(material_5);
materials.push(material_6);
// 创建一个立方体
var cubeGeometry = new THREE.BoxGeometry(300, 300, 300);
var cube = new THREE.Mesh(cubeGeometry, materials);
//将立方体添加到场景中
scene.add(cube);
// 环境光
var ambientLight = new THREE.AmbientLight ( 0xffffff, 0.2);
scene.add( ambientLight );
// 点光源
var pointLight = new THREE.PointLight( 0xffffff, 1 );
pointLight.position.set( 325, 350, 325 );
scene.add( pointLight );
function animate() {
requestAnimationFrame( animate )
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera )
}
animate();
}
// 页面加载成功后调init()方法
window.onload = init;
</script>
</body>
</html>
为了演示,我把本地的图片换成了在线免费的图片了。
如果觉得文章写得还凑合,还麻烦你动动小手帮忙点个赞呗。你的支持是我更文的动力。目前在写的系列有下面几个系统:
- MyBatis源码解读
- 设计模式
- 一起学Three.js
- Spring Boot
- Spring Cloud
都是一些平时工作中用到的知识点的个人总结和学习笔记。