three.js 箭头ArrowHelper的实践应用
效果:
代码:
<template>
<div>
<el-container>
<el-main>
<div class="box-card-left">
<div id="threejs" style="border: 1px solid red"></div>
</div>
</el-main>
</el-container>
</div>
</template>
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export default {
data() {
return {
sphereGeometry: null,
group: null,
camera: null,
mesh: null,
renderer: null,
requestAnimationFrame_time: null,
B: null,
lengthVal: 0,
normalizeVal: null,
css3DRenderer: null,
};
},
mounted() {
this.name = this.$route.query.name;
this.init();
},
methods: {
goBack() {
this.$router.go(-1);
},
init() {
// 创建场景对象
this.scene = new this.$three.Scene();
// 调用方法创建点模型 A
this.createPoint([0,40,0]);
// 调用方法创建点模型 B
this.createPoint([50,0,0]);
this.createBox();
// 创建环境光对象
const ambientLight = new this.$three.AmbientLight(0xffffff,0.8);
this.scene.add(ambientLight);
// 创建箭头对象
/**
* ArrowHelper(dir : Vector3, origin : Vector3, length : Number, hex : Number, headLength : Number, headWidth : Number )
dir -- 基于箭头原点的方向. 必须为单位向量.
origin -- 箭头的原点.
length -- 箭头的长度. 默认为 1.
hex -- 定义的16进制颜色值. 默认为 0xffff00.
headLength -- 箭头头部(锥体)的长度. 默认为箭头长度的0.2倍(0.2 * length).
headWidth -- The width of the head of the arrow. Default is 0.2 * headLength.
*/
/**
* 计算箭头需要的参数;箭头是从A指向B
*/
const A = new this.$three.Vector3(0,40,0);
const B = new this.$three.Vector3(50,0,0);
// 箭头方向的单位向量
const dir = B.clone().sub(A).normalize();
// 箭头原点 是 A
const origin = A;
// 箭头长度---就是 A 点到 B 点的距离;使用 length()方法可以计算得到
const length = B.clone().sub(A).length();
const hex = 0xffddaa;
const arrowHelper = new this.$three.ArrowHelper(dir, origin, length, hex);
this.scene.add(arrowHelper);
// 创建坐标轴辅助对象
const axesHelper = new this.$three.AxesHelper(200);
this.scene.add(axesHelper);
// 创建相机对象
this.camera = new this.$three.PerspectiveCamera();
this.camera.position.set(150,150,150);
this.camera.lookAt(0,0,0);
// 创建渲染器对象
this.renderer = new this.$three.WebGLRenderer();
this.renderer.setSize(1000,800);
this.renderer.render(this.scene, this.camera);
window.document.getElementById("threejs").appendChild(this.renderer.domElement);
const controls = new OrbitControls(this.camera, this.renderer.domElement);
controls.addEventListener("change", e => {
this.renderer.render(this.scene, this.camera);
})
},
/**
* 创建点模型的方法,
* point_position: 数组类型,数组里有且只有三个元素,
* */
createPoint(point_position) {
// 创建缓存几何体对象
const bufferGeometry = new this.$three.BufferGeometry();
// 创建类型化数组来存放顶点数据
const vectors = new Float32Array(point_position);
// 创建缓存属性来格式化顶点数据
const bufferAttribute = new this.$three.BufferAttribute(vectors,3);
// 设置缓存几何体的位置属性
bufferGeometry.setAttribute("position", bufferAttribute);
// 创建点材质对象
const material = new this.$three.PointsMaterial({
color: 0x99dd,
size: 10
});
// 创建点模型对象
const point = new this.$three.Points(bufferGeometry, material);
this.scene.add(point);
},
createBox() {
const geometry = new this.$three.BoxGeometry(50, 50, 50);
const material = new this.$three.MeshLambertMaterial({
color: 0x00ffff,
});
const mesh = new this.$three.Mesh(geometry, material);
const p = mesh.geometry.attributes.position; // 顶点坐标集合
const n = mesh.geometry.attributes.normal; // 顶点法线数据集合
// 顶点数量
const count = p.count;
for(let i = 0; i < count; i ++) {
// 该向量是单位向量了
const dir = new this.$three.Vector3(n.getX(i), n.getY(i), n.getZ(i));
// 箭头起点
const origin = new this.$three.Vector3(p.getX(i), p.getY(i), p.getZ(i));
const arrowHelper = new this.$three.ArrowHelper(dir, origin, 20);
mesh.add(arrowHelper);
}
// mesh模型沿着 z 轴正向移动 50
mesh.translateZ(50);
this.scene.add(mesh);
}
},
};
</script>
<style lang="less" scoped>
.box-card-left {
display: flex;
align-items: flex-start;
flex-direction: row;
width: 100%;
.box-right {
img {
width: 500px;
user-select: none;
}
}
}
</style>