RAS-WEB/src/views/screen/R_D_Environment/component/ThreeBG.vue
2024-11-18 17:11:33 +08:00

202 lines
6.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div ref="threeContainer"></div>
</template>
<script setup>
import * as THREE from 'three';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { CSS3DObject, CSS3DRenderer } from 'three/examples/jsm/Addons.js';
import { onMounted, ref } from 'vue';
const threeContainer = ref(null);
let camera, scene, renderer, model, controls, cssRenderer;
let width = 1920;
let height = 1080;
let text = ref('标注1');
const init = () => {
scene = new THREE.Scene();
// scene.background = new THREE.Color(0x100c2a);//0x100c2a
// scene.background.setAlpha(0);
camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 2000);
camera.position.set(40, 300, 200);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(width, height);
threeContainer.value.appendChild(renderer.domElement);
cssRenderer = initLabelRenderer(threeContainer.value);
const objLoader = new OBJLoader();
let mtlLoader = new MTLLoader();
mtlLoader.load('/src/assets/obj/goats_R&D.mtl', function (materials) {
materials.preload();
objLoader.setMaterials(materials);
objLoader.load('/src/assets/obj/goats_R&D.obj', function (obj) {
var scale = 0.07 / obj.scale.x;
obj.scale.set(scale, scale, scale);
model = obj;
const box = new THREE.Box3().setFromObject(model);
const size = box.getSize(new THREE.Vector3())
// console.log(size,'-----');
obj.position.set(-size.x * 0.5, -size.y * 0.1, -size.z * 0.5);
obj.children.forEach((child) => {
const c = child;
const cm = c.material;
cm.emissive = cm.color;
cm.emissiveMap = cm.map;
});
addMarks(text.value);
scene.add(model);
animate();
});
});
// loader.load(
// '/src/assets/obj/goats_R&D.obj',
// (obj) => {
// var scale = 0.1 / obj.scale.x;
// obj.scale.set(scale, scale, scale);
// model = obj;
// // 添加光照
// // scene.add(new THREE.AmbientLight(0x404040));
// scene.add(new THREE.DirectionalLight());
// scene.add(model);
// },
// (xhr) => {
// console.log((xhr.loaded / xhr.total * 100) + '% loaded');
// },
// (error) => {
// console.error('An error happened: ', error);
// }
// );
controls = new OrbitControls(camera, cssRenderer.domElement);
controls.enableDamping = true;
animate();
};
// 初始化标注渲染器
const initLabelRenderer = boxElement => {
const labelRenderer = new CSS3DRenderer();
labelRenderer.setSize(width, height);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = 0;
boxElement.appendChild(labelRenderer.domElement);
return labelRenderer;
};
function addMarks(text) {
//把传入的标注文字通过 canvas 修改为可以添加到场景中的 texture
const offScreenCanvas = document.createElement('canvas');
const offScreenCtx = offScreenCanvas.getContext('2d');
// 配置字体、大小、颜色等
offScreenCtx.font = '16px 黑体';
const txt = text;
const textWidth = offScreenCtx.measureText(txt).width;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (ctx !== null) {
// pixelRatio: 像素密度
canvas.width = (5 + textWidth + 5) * 2;
canvas.height = 18 * 2;
ctx.setTransform(2, 0, 0, 2, 0, 0);
ctx.font = '16px 黑体';
ctx.fillStyle = '#fff'; //标注背景颜色
ctx.fillRect(0, 0, 5 + textWidth + 5, 18);
ctx.fillStyle = '#000'; //标注字体颜色
ctx.fillText(txt, 5, 16);
}
// 将标注变成可以添加到场景中的 texture 对象
const texture = new THREE.CanvasTexture(canvas);
var geometry2 = new THREE.BufferGeometry();
var material = new THREE.LineBasicMaterial({ vertexColors: true });
var color1 = new THREE.Color(0xffffff), color2 = new THREE.Color(0xffffff);
//定义第一条线
var p3 = new THREE.Vector3(0, 50, 40);
var p4 = new THREE.Vector3(4, 23.5, 10);
const points = [];
points.push(p3);
points.push(p4);
// geometry2.vertices.push(p3);
// geometry2.vertices.push(p4);
// geometry2.colors.push(color1, color2);
geometry2.setFromPoints(points);
//把线条添加到场景中
var line2 = new THREE.Line(geometry2, material, THREE.LinePieces);
scene.add(line2);
//定义第一个标签
/**精灵图 */
// var spriteMaterial2 = new THREE.SpriteMaterial({ map: texture, color: 0xffffff });
// var sprite2 = new THREE.Sprite(spriteMaterial2);
// sprite2.position.set(0, 50, 40);
// sprite2.scale.set(15, 5, 0);
// scene.add(sprite2);
/** CSS3D */
const label = new CSS3DObject(document.createElement('div'));
label.position.set(0, 50, 40);
label.scale.set(0.5, 0.5, 0.5);
label.element.style.backgroundColor = '#fff';
label.element.innerText = text;
scene.add(label);
// 调整显示方向
// 假设我们要将HTML元素旋转90度绕Y轴使其从正前方指向右方
label.rotation.set(-Math.PI / 4,0, 0);
//定义标记点
var radius = 0.5, segemnt = 16, rings = 16;
var sphereMaterial = new THREE.MeshLambertMaterial({ color: 0x9afc00 });
var sphere101 = new THREE.Mesh(new THREE.SphereGeometry(radius, segemnt, rings), sphereMaterial);
sphere101.position.set(4, 23.5, 10);
scene.add(sphere101);
// var group = new THREE.Object3D();
// group.add(line2);
// group.add(sphere101);
// group.add(sprite2);
// scene.add(group);
}
const animate = () => {
requestAnimationFrame(animate);
renderer.render(scene, camera);
cssRenderer.render(scene, camera);
controls.update();
};
onMounted(() => {
init();
window.addEventListener('resize', onWindowResize);
});
const onWindowResize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
onMounted(() => {
window.removeEventListener('resize', onWindowResize);
});
</script>
<style>
#threeContainer {
width: 1920px;
height: 1080px;
/* 根据需要调整位置 */
overflow: hidden;
}
</style>