线段几何体材质,分为LineBasicMaterial
和LineDashedMaterial
,线段上只有顶点没有面。
LineBasicMaterial:通过线段基础材质,可以设置线段的颜色、宽度和连接点。
LineDashedMaterial:虚线材质的基本属性跟基础线段材质一样,但是可以指定短划线的和间距空格的长度。
LineBasicMaterial 属性
名称 | 描述 |
---|---|
color | 指定线框的颜色默认为白色,如果指定vertexColors,这个属性会被忽略 |
linewidth | 指定线框的宽度,默认为1,在WebGLRenderer 不支持该属性 |
linecap | 线框端点形状,属于2D画布lineCap属性,它被WebGL渲染器忽略 |
linejoin | 线框节点外观,属于2D画布lineCap属性,它被WebGL渲染器忽略 |
LineDashedMaterial 属性
lineDashedMaterial
除了与LineBasicMaterial
有一样的属性外,还具有几个额外的属性。
名称 | 描述 |
---|---|
dashSize | 虚线的长度,默认为3 |
gapSize | 中间缝隙的大小,默认为1 |
scale | 虚线的缩放比例,默认为1,若这个值小于1**dashSize**和gapSize就会增大,小于1则变小 |
注意:虚线材质,需要计算线段之间的距离,所以需要添加这行代码
lines.computeLineDistances()
,否则显示的是实线。
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LineBasicMaterial 和 LineDashedMaterial 线段几何材质</title>
<style>
body {
margin: 0;
overflow: hidden; /*溢出隐藏*/
}
</style>
<script src="../../libs/build/three-r93.min.js"></script>
<script src="../../libs/examples/js/controls/OrbitControls.js"></script>
<script src="../../libs/examples/js/libs/dat.gui.min.js"></script>
<script src="../../libs/examples/js/libs/stats.min.js"></script>
<script src="../../libs/examples/js/Detector.js"></script>
</head>
<body>
<script>
let stats = initStats();
let scene, camera, renderer, lines, controls, guiControls;
/* 场景 */
function initScene() {
scene = new THREE.Scene();
}
/* 相机 */
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 5000);
camera.position.set(0, 1000, 2000);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
/* 渲染器 */
function initRenderer() {
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
/* 灯光 */
function initLight() {
}
/* 控制器 */
function initControls() {
controls = new THREE.OrbitControls(camera, renderer.domElement);
// 添加惯性
controls.enableDamping = true;
// 最大偏移角度
controls.maxPolarAngle = 0.49 * Math.PI;
controls.enableRotate = false;
}
/* 调试插件 */
let gui;
function initGui() {
guiControls = new function () {
this.rotation = true;
this.vertexColors = true;
this.color = material.color.getStyle();
this.opacity = material.opacity;
this.transparent = material.transparent;
this.lineMaterial = 'LineBasicMaterial';
};
gui = new dat.GUI();
gui.add(guiControls, 'rotation').onChange(function (e) {
step = e ? 0.005 : 0;
});
gui.add(guiControls, 'vertexColors').onChange(function (e) {
material.vertexColors = e ? true : false;
material.needsUpdate = true;
});
gui.addColor(guiControls, 'color').onChange(function (e) {
material.color.setStyle(e);
material.needsUpdate = true;
});
gui.add(guiControls, 'opacity', 0, 1).onChange(function (e) {
material.opacity = e;
});
gui.add(guiControls, 'transparent').onChange(function (e) {
material.transparent = e;
});
gui.add(guiControls, 'lineMaterial', ['LineBasicMaterial', 'LineDashedMaterial']).onChange(function (e) {
switch (e) {
case 'LineBasicMaterial':
material = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors});
break;
case 'LineDashedMaterial':
material = new THREE.LineDashedMaterial({vertexColors: THREE.VertexColors, gapSize: 2});
break;
}
lines.material = material;
});
}
/* 场景中的内容 */
let material;
function initContent() {
// 分段数
let segments = 1000;
let geometry = new THREE.BufferGeometry();
material = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors});
let positions = [];
let colors = [];
let r = 1000;
for (let i = 0; i < segments; i++) {
let x = Math.random() * r - r / 2;
let y = Math.random() * r - r / 2;
let z = Math.random() * r - r / 2;
// 位置
positions.push(x, y, z,);
// 颜色
colors.push((x / r) + 0.5);
colors.push((y / r) + 0.5);
colors.push((z / r) + 0.5);
}
// 次数传递的 position 和 color 是固定的
geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.addAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
geometry.computeBoundingSphere();
lines = new THREE.Line(geometry, material);
lines.computeLineDistances();
scene.add(lines);
}
/* 性能插件 */
function initStats() {
let stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
return stats;
}
/* 更新 */
let step = 0.005;
function update() {
stats.update();
controls.update();
lines.rotation.y -= step;
lines.rotation.x -= step;
}
/* 初始化 */
function init() {
// 兼容性判断,若不兼容会提示信息
if (!Detector.webgl) Detector.addGetWebGLMessage();
initScene();
initCamera();
initRenderer();
initLight();
initControls();
initContent();
initGui();
window.addEventListener('resize', onWindowResize, false);
}
/* 窗口变动触发的方法 */
function onWindowResize() {
// 重新设置相机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 更新相机投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器大小
renderer.setSize(window.innerWidth, window.innerHeight);
}
/* 循环渲染 */
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
update();
}
/* 页面绘制完后加载 */
window.onload = function () {
init();
animate();
};
</script>
</body>
</html>