demo案例
THREE.LineBasicMaterial
是 three.js 中用来创建用于绘制线条的基本材质。以下是它的入参、出参、方法和属性的详细说明。
入参 (Constructor Parameters)
THREE.LineBasicMaterial
构造函数可以接收一个包含多个属性的对象。常用属性如下:
const material = new THREE.LineBasicMaterial( {
color: 0xffffff, // 颜色
linewidth: 1, // 线宽(只有在WebGLRenderer中有效)
linecap: 'round', // 线段端点样式,可选值:'butt', 'round', 'square'
linejoin: 'round', // 线段连接处样式,可选值:'round', 'bevel', 'miter'
opacity: 1.0, // 不透明度
transparent: false, // 是否透明
vertexColors: false, // 是否使用顶点颜色
fog: true // 是否受雾影响
});
出参 (Return Value)
构造函数 new THREE.LineBasicMaterial
创建并返回一个 THREE.LineBasicMaterial
对象。
方法 (Methods)
THREE.LineBasicMaterial
继承自 THREE.Material
,因此具有 THREE.Material
的所有方法。常用的方法包括:
.copy(source)
: 复制源材质的所有属性到当前材质。.clone()
: 克隆当前材质,返回一个新的材质实例。.dispose()
: 释放材质使用的资源。.setValues(parameters)
: 设置材质的属性。
属性 (Properties)
THREE.LineBasicMaterial
继承自 THREE.Material
,并有以下特有属性:
.color
:THREE.Color
线条的颜色,默认为白色 (0xffffff)。.linewidth
:number
线条的宽度。注意,线宽的实际效果在不同平台和设备上可能有所不同。.linecap
:string
线段端点的样式,可选值为'butt'
,'round'
,'square'
,默认值为'round'
。.linejoin
:string
线段连接处的样式,可选值为'round'
,'bevel'
,'miter'
,默认值为'round'
。.vertexColors
:boolean
指定是否使用顶点颜色。可选值为THREE.NoColors
,THREE.VertexColors
。.fog
:boolean
指定材质是否受雾影响,默认值为true
。.opacity
:number
不透明度,取值范围为 0.0 到 1.0,默认值为 1.0。.transparent
:boolean
指定材质是否透明,默认值为false
。
示例
以下是一个使用 THREE.LineBasicMaterial
绘制线条的简单示例:
// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建线条的几何体
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
0.0, 1.0, 0.0
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
// 创建线条的材质
const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
// 创建线条对象
const line = new THREE.Line(geometry, material);
scene.add(line);
// 设置相机位置
camera.position.z = 5;
// 渲染函数
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - buffergeometry - lines - indexed</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="container"></div> <!-- 容器元素 -->
<div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - buffergeometry - lines - indexed</div> <!-- 信息栏 -->
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three'; // 导入 three.js
import Stats from 'three/addons/libs/stats.module.js'; // 导入 Stats 库
let container, stats; // 定义容器和统计对象
let camera, scene, renderer; // 定义相机、场景和渲染器
let parent_node; // 定义父节点
init(); // 初始化函数
animate(); // 动画函数
function init() {
container = document.getElementById( 'container' ); // 获取容器元素
camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 10000 ); // 创建透视相机
camera.position.z = 9000; // 设置相机位置
scene = new THREE.Scene(); // 创建场景
const geometry = new THREE.BufferGeometry(); // 创建几何体
const material = new THREE.LineBasicMaterial( { vertexColors: true } ); // 创建材质
const indices = []; // 定义索引数组
const positions = []; // 定义位置数组
const colors = []; // 定义颜色数组
let next_positions_index = 0; // 下一个顶点索引
const iteration_count = 4; // 迭代次数
const rangle = 60 * Math.PI / 180.0; // 角度
function add_vertex( v ) {
// 添加顶点
positions.push( v.x, v.y, v.z );
colors.push( Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 1 );
return next_positions_index ++;
}
// 简单的 Koch 曲线迭代
function snowflake_iteration( p0, p4, depth ) {
if ( -- depth < 0 ) {
const i = next_positions_index - 1; // p0 已经在数组中
add_vertex( p4 );
indices.push( i, i + 1 );
return;
}
const v = p4.clone().sub( p0 );
const v_tier = v.clone().multiplyScalar( 1 / 3 );
const p1 = p0.clone().add( v_tier );
const angle = Math.atan2( v.y, v.x ) + rangle;
const length = v_tier.length();
const p2 = p1.clone();
p2.x += Math.cos( angle ) * length;
p2.y += Math.sin( angle ) * length;
const p3 = p0.clone().add( v_tier ).add( v_tier );
snowflake_iteration( p0, p1, depth );
snowflake_iteration( p1, p2, depth );
snowflake_iteration( p2, p3, depth );
snowflake_iteration( p3, p4, depth );
}
// 生成雪花
function snowflake( points, loop, x_offset ) {
for ( let iteration = 0; iteration != iteration_count; iteration ++ ) {
add_vertex( points[ 0 ] );
for ( let p_index = 0, p_count = points.length - 1; p_index != p_count; p_index ++ ) {
snowflake_iteration( points[ p_index ], points[ p_index + 1 ], iteration );
}
if ( loop ) snowflake_iteration( points[ points.length - 1 ], points[ 0 ], iteration );
// 平移输入曲线
for ( let p_index = 0, p_count = points.length; p_index != p_count; p_index ++ ) {
points[ p_index ].x += x_offset;
}
}
}
let y = 0;
// 创建不同形状的雪花
snowflake(
[
new THREE.Vector3( 0, y, 0 ),
new THREE.Vector3( 500, y, 0 )
],
false, 600
);
y += 600;
snowflake(
[
new THREE.Vector3( 0, y, 0 ),
new THREE.Vector3( 250, y + 400, 0 ),
new THREE.Vector3( 500, y, 0 )
],
true, 600
);
y += 600;
snowflake(
[
new THREE.Vector3( 0, y, 0 ),
new THREE.Vector3( 500, y, 0 ),
new THREE.Vector3( 500, y + 500, 0 ),
new THREE.Vector3( 0, y + 500, 0 )
],
true, 600
);
y += 1000;
snowflake(
[
new THREE.Vector3( 250, y, 0 ),
new THREE.Vector3( 500, y, 0 ),
new THREE.Vector3( 250, y, 0 ),
new THREE.Vector3( 250, y + 250, 0 ),
new THREE.Vector3( 250, y, 0 ),
new THREE.Vector3( 0, y, 0 ),
new THREE.Vector3( 250, y, 0 ),
new THREE.Vector3( 250, y - 250, 0 ),
new THREE.Vector3( 250, y, 0 )
],
false, 600
);
geometry.setIndex( indices ); // 设置索引
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) ); // 设置位置属性
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) ); // 设置颜色属性
geometry.computeBoundingSphere(); // 计算包围球
const lineSegments = new THREE.LineSegments( geometry, material ); // 创建线段
lineSegments.position.x -= 1200; // 平移位置
lineSegments.position.y -= 1200; // 平移位置
parent_node = new THREE.Object3D(); // 创建父节点
parent_node.add( lineSegments ); // 添加线段到父节点
scene.add( parent_node ); // 将父节点添加到场景
renderer = new THREE.WebGLRenderer(); // 创建渲染器
renderer.setPixelRatio( window.devicePixelRatio ); // 设置像素比
renderer.setSize( window.innerWidth, window.innerHeight ); // 设置渲染器大小
container.appendChild( renderer.domElement ); // 将渲染器添加到容器
stats = new Stats(); // 创建统计对象
container.appendChild( stats.dom ); // 将统计对象添加到容器
window.addEventListener( 'resize', onWindowResize ); // 添加窗口大小改变事件监听
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight; // 更新相机宽高比
camera.updateProjectionMatrix(); // 更新相机投影矩阵
renderer.setSize( window.innerWidth, window.innerHeight ); // 更新渲染器大小
}
function animate() {
requestAnimationFrame( animate ); // 请求动画帧
render(); // 渲染场景
stats.update(); // 更新统计信息
}
function render() {
const time = Date.now() * 0.001; // 获取当前时间
parent_node.rotation.z = time * 0.5; // 旋转父节点
renderer.render( scene, camera ); // 渲染场景
}
</script>
</body>
</html>
压图地址