当前位置:   article > 正文

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

float32bufferattribute

系列文章目录

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



前言

最近开始入坑前端3D建站,跟大家一起慢慢深入three.js做网站3D

这篇文章给大家讲下three.js 画线升级版,3D炫酷划线


一、省略部分

官网,介绍,以及引入库,参看文章片头系列文章:01 第一个3D网站

二、使用方法

创建一个dom元素

<div id="container"></div>
  • 1

创建初始化方法

这里面使用到了我们前几篇文章讲到的,创建场景,创建集合,渲染等这里不再详细讲述


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);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

知识点:
这里面采用循环,将颜色值和位置通过循环的方式,存储并设置到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];

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132

知识点:
为了实现动画效果,除了采用了熏染循环,对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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153

效果

在这里插入图片描述

总结

以上就是今天要讲的内容,本文仅仅简单介绍了three.js的使用,而three.js提供了非常多的3D显示功能,后续文章,我将带大家慢慢深入了解。

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/84967
推荐阅读
相关标签
  

闽ICP备14008679号