Three.js一学就会系列:03 炫酷3D划线

系列文章目录

Three.js一学就会系列:01 第一个3D网站
Three.js一学就会系列:02 画线



前言

最近开始入坑前端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显示功能,后续文章,我将带大家慢慢深入了解。

如果觉得有用欢迎点赞关注
有问题私信我!!~~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

成茂峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值