系列文章目录
Three.js一学就会系列:01 第一个3D网站
Three.js一学就会系列:02 画线
文章目录
- 系列文章目录
- 前言
- 一、省略部分
- 二、使用方法
- 创建一个dom元素
- 创建初始化方法
- 线条动起来
- 效果
- 总结
前言
最近开始入坑前端3D建站,跟大家一起慢慢深入three.js做网站3D
这篇文章给大家讲下three.js 画线升级版,3D炫酷划线
一、省略部分
官网,介绍,以及引入库,参看文章片头系列文章:01 第一个3D网站
二、使用方法
创建一个dom元素
<div id="container"></div>
创建初始化方法
这里面使用到了我们前几篇文章讲到的,创建场景,创建集合,渲染等这里不再详细讲述
let container;
let camera, scene, renderer;
let line;
const segments = 10000;
const r = 800;
let t = 0;
init();
function init() {
container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(27, window.innerWidth / window.innerHeight, 1, 4000);
camera.position.z = 2750;
scene = new THREE.Scene();
const geometry = new THREE.BufferGeometry();
// 材质 顶点着色
const material = new THREE.LineBasicMaterial({ vertexColors: true });
// 位置数组
const positions = [];
// 随机颜色数组
const colors = [];
for (let i = 0; i < segments; i++) {
const x = Math.random() * r - r / 2;
const y = Math.random() * r - r / 2;
const z = Math.random() * r - r / 2;
// positions
positions.push(x, y, z);
// colors
colors.push((x / r) + 0.5);
colors.push((y / r) + 0.5);
colors.push((z / r) + 0.5);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
line = new THREE.Line(geometry, material);
scene.add(line);
// 用WebGL渲染出你精心制作的场景
renderer = new THREE.WebGLRenderer();
// 设置设备像素比。通常用于避免HiDPI设备上绘图模糊
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
}
知识点:
这里面采用循环,将颜色值和位置通过循环的方式,存储并设置到BufferGeometry对应中,
setAttribute:设置几何属性 'position’位置,'color’颜色
Float32BufferAttribute:第一个参数为数据,第二个参数为分隔数,坐标(x,y,z)所以采用3
线条动起来
let container, clock;
letcamera, scene, renderer;
let line;
const segments = 10000;
const r = 800;
let t = 0;
init();
animate();
function init() {
container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(27, window.innerWidth / window.innerHeight, 1, 4000);
camera.position.z = 2750;
scene = new THREE.Scene();
// 用于跟踪时间
clock = new THREE.Clock();
const geometry = new THREE.BufferGeometry();
// 材质 顶点着色
const material = new THREE.LineBasicMaterial({ vertexColors: true });
// 位置数组
const positions = [];
// 随机颜色数组
const colors = [];
for (let i = 0; i < segments; i++) {
const x = Math.random() * r - r / 2;
const y = Math.random() * r - r / 2;
const z = Math.random() * r - r / 2;
// positions
positions.push(x, y, z);
// colors
colors.push((x / r) + 0.5);
colors.push((y / r) + 0.5);
colors.push((z / r) + 0.5);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 生成定点位置
generateMorphTargets(geometry);
// 计算边界
geometry.computeBoundingSphere();
line = new THREE.Line(geometry, material);
scene.add(line);
// 用WebGL渲染出你精心制作的场景
renderer = new THREE.WebGLRenderer();
// 设置设备像素比。通常用于避免HiDPI设备上绘图模糊
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
// 监听窗口尺寸变化
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
// 摄像机视锥体的长宽比,通常是使用画布的宽/画布的高。默认值是1(正方形画布)
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机投影矩阵 (参数更新后需要更新)
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// 渲染循环
function animate() {
requestAnimationFrame(animate);
render();
}
// 渲染 动画
function render() {
const delta = clock.getDelta();
const time = clock.getElapsedTime();
line.rotation.x = time * 0.25;
line.rotation.y = time * 0.5;
t += delta * 0.5;
line.morphTargetInfluences[0] = Math.abs(Math.sin(t));
// line.morphTargetInfluences[0] = 0;
renderer.render(scene, camera);
}
// 位置
function generateMorphTargets(geometry) {
const data = [];
for (let i = 0; i < segments; i++) {
const x = Math.random() * r - r / 2;
const y = Math.random() * r - r / 2;
const z = Math.random() * r - r / 2;
data.push(x, y, z);
}
const morphTarget = new THREE.Float32BufferAttribute(data, 3);
morphTarget.name = 'target1';
geometry.morphAttributes.position = [morphTarget];
}
知识点:
为了实现动画效果,除了采用了熏染循环,对line进行了位置更新
generateMorphTargets方法,用于生成随机后的定点 赋值到geometry.morphAttributes.position
computeBoundingSphere:计算边界
Clock:用于计算时间,方便对动画效果支持
完整代码(实例)
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<script src="./three.js"></script>
<div id="container"></div>
<!-- <script src="https://threejs.org/build/three.js"></script> -->
<script>
let container, clock;
let camera, scene, renderer;
let line;
const segments = 10000;
const r = 800;
let t = 0;
init();
animate();
function init() {
container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(27, window.innerWidth / window.innerHeight, 1, 4000);
camera.position.z = 2750;
scene = new THREE.Scene();
// 用于跟踪时间
clock = new THREE.Clock();
const geometry = new THREE.BufferGeometry();
// 材质 顶点着色
const material = new THREE.LineBasicMaterial({ vertexColors: true });
// 位置数组
const positions = [];
// 随机颜色数组
const colors = [];
for (let i = 0; i < segments; i++) {
const x = Math.random() * r - r / 2;
const y = Math.random() * r - r / 2;
const z = Math.random() * r - r / 2;
// positions
positions.push(x, y, z);
// colors
colors.push((x / r) + 0.5);
colors.push((y / r) + 0.5);
colors.push((z / r) + 0.5);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 生成定点位置
generateMorphTargets(geometry);
// 计算边界
geometry.computeBoundingSphere();
line = new THREE.Line(geometry, material);
scene.add(line);
// 用WebGL渲染出你精心制作的场景
renderer = new THREE.WebGLRenderer();
// 设置设备像素比。通常用于避免HiDPI设备上绘图模糊
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
// 监听窗口尺寸变化
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
// 摄像机视锥体的长宽比,通常是使用画布的宽/画布的高。默认值是1(正方形画布)
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机投影矩阵 (参数更新后需要更新)
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// 渲染循环
function animate() {
requestAnimationFrame(animate);
render();
}
// 渲染 动画
function render() {
const delta = clock.getDelta();
const time = clock.getElapsedTime();
line.rotation.x = time * 0.25;
line.rotation.y = time * 0.5;
t += delta * 0.5;
line.morphTargetInfluences[0] = Math.abs(Math.sin(t));
// line.morphTargetInfluences[0] = 0;
renderer.render(scene, camera);
}
// 位置
function generateMorphTargets(geometry) {
const data = [];
for (let i = 0; i < segments; i++) {
const x = Math.random() * r - r / 2;
const y = Math.random() * r - r / 2;
const z = Math.random() * r - r / 2;
data.push(x, y, z);
}
const morphTarget = new THREE.Float32BufferAttribute(data, 3);
morphTarget.name = 'target1';
geometry.morphAttributes.position = [morphTarget];
}
</script>
</body>
</html>
效果
总结
以上就是今天要讲的内容,本文仅仅简单介绍了three.js的使用,而three.js提供了非常多的3D显示功能,后续文章,我将带大家慢慢深入了解。
如果觉得有用欢迎点赞关注
有问题私信我!!~~