<template>
<div>
<div id="three"></div>
</div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
export default {
data() {
return {
scene: {}, // 场景
camera: {}, // 摄像机
renderer: {}, // 渲染器
parts: [], // 几何图形储存器
mixer: null, // 动画
clock: {}
};
},
mounted(){
this.threes();
this.resize(); // 自适应
this.mousedown(); // 鼠标点击事件
this.mod();
},
methods: {
// 浏览器窗口发生变化时 自适应
resize(){
window.addEventListener('resize', () => {
// 初始化摄像机
this.camera.aspect = window.innerWidth/window.innerHeight;
// 摄像机矩阵效果
this.camera.updateProjectionMatrix();
// 初始化渲染器
this.renderer.setSize(window.innerWidth, window.innerHeight);
})
},
threes() {
// 创建场景
this.scene = new THREE.Scene();
// 创建摄像机 // 参数含义: 视角、窗口投影长宽比、摄像机从哪里开始渲染、距离摄像机多远截至渲染
this.camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
// 创建three渲染器 参数: 去锯齿
this.renderer = new THREE.WebGLRenderer({ antialias: true });
// 设置渲染器场景背景颜色
this.renderer.setClearColor(0x000000, .2)
// 开启阴影,加上阴影渲染
this.renderer.shadowMapEnabled = true;
// 设置渲染器场景大小 参数: 宽,高
this.renderer.setSize(window.innerWidth, window.innerHeight);
// 把渲染器添加到页面中
document.getElementById('three').appendChild(this.renderer.domElement);
this.plane() // 平面模型
this.wall({x: 500, y: 60, z: 10}, {x: 0, y: 30, z: -145}) // 外墙壁 1
this.wall({x: 500, y: 60, z: 10}, {x: 0, y: 30, z: 145}) // 外墙壁 2
this.wall({x: 10, y: 60, z: 300}, {x: 250, y: 30, z: 0}) // 外墙壁 3
this.wall({x: 10, y: 60, z: 300}, {x: -250, y: 30, z: 0}) // 外墙壁 4
this.wall({x: 10, y: 60, z: 120}, {x: 160, y: 30, z: -80}) // 内墙壁 5
this.wall({x: 90, y: 60, z: 10}, {x: 200, y: 30, z: -20}) // 内墙壁 6
for(let i = 0; i < 4; i ++){
// this.chartlet(-220, 30, (-100 + i * 41)) // 横排
this.chartlet((-220 + i * 35), 30, -100) // 纵排
this.chartlet((-220 + i * 35), 30, -55) // 纵排
this.chartlet((-220 + i * 35), 30, 100) // 纵排
this.chartlet((-220 + i * 35), 30, 55) // 纵排
}
this.vavAair(100,50,135)
// 将网格对象添加到场景中
this.parts.forEach(item => {
this.scene.add(item);
});
// 创建光源
this.createLight()
// 辅助坐标系 参数250表示坐标系大小,可以根据场景大小去设置
this.axesHelper = new THREE.AxesHelper(500);
// 将坐标系添加到场景中
this.scene.add(this.axesHelper);
// 摄像机空间轴位置
this.camera.position.z = 300
this.camera.position.y = 350
this.camera.position.x = 100
// 创建鼠标控件对象
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.animate()
},
// 添加帧渲染
animate(){
let that = this
requestAnimationFrame(this.animate);
// 网格对象自动旋转
// this.cube.rotation.x += 0.005
// this.cube.rotation.y += 0.005
if (this.mixer !== null){
that.mixer.update(that.clock.getDelta());
}
// 初始化controls
this.controls.update()
this.render()
},
// 渲染器渲染场景和摄像机
render(){
this.renderer.render(this.scene, this.camera)
},
// 创建光源
createLight () {
// 环境光
const ambint = new THREE.AmbientLight(0xffffff)
this.scene.add(ambint)
// 聚光灯光源
this.spotLight(0x03FF6A, 245, 60, 140, 600)
this.spotLight(0xff0000, -245, 60, 140, 500)
// this.pointLight(0xffffff, 0, 900, 0, 1000)
this.pointLight(0x0070ee, 205, 100, -80, 130)
},
// 聚光灯光源
spotLight (color, x, y, z, dis) {
const spotLight = new THREE.SpotLight(color)
spotLight.position.set(x, y, z); // 光源位置
spotLight.castShadow = true; //开启灯光投射阴影
spotLight.intensity = 3 // 强度
spotLight.angle = 0.3; // 角度
spotLight.penumbra = 1; // 半影
spotLight.decay = 1; // 衰退
spotLight.distance = dis; // 距离
this.scene.add(spotLight)
// 辅助线
// let spotLightHelper = new THREE.SpotLightHelper(spotLight, 0x976fb6);
// this.scene.add(spotLightHelper)
// 光源寄托
this.createLightView(color, x, y, z)
},
// 点光灯光源
pointLight (color, x, y, z, dis) {
const pointLight = new THREE.PointLight(color)
pointLight.position.set(x, y, z); // 光源位置
pointLight.castShadow = true; //开启灯光投射阴影
pointLight.intensity = 4 // 强度
// pointLight.angle = 0.3; // 角度
pointLight.penumbra = 1; // 半影
// pointLight.decay = 1; // 衰退
pointLight.distance = dis; // 距离
this.scene.add(pointLight)
// 辅助线
// let spotLightHelper = new THREE.SpotLightHelper(pointLight, 0x976fb6);
// this.scene.add(spotLightHelper)
// 光源寄托
this.createLightView(color, x, y, z)
},
// 光源寄托
createLightView(color, x, y, z){
let geometry = new THREE.SphereGeometry(3, 3, 3);
let material = new THREE.MeshPhongMaterial({ color });
let cube = new THREE.Mesh(geometry, material);
cube.position.set(x, y, z)
this.scene.add(cube)
},
// 平面模型
plane(){
let geometry = new THREE.PlaneGeometry(640, 400, 1, 1);
let material = new THREE.MeshPhongMaterial({ color: 0xE5E5E5, wireframe: false });
let cube = new THREE.Mesh(geometry, material);
cube.rotation.x = -0.5 * Math.PI
cube.position.set(0, 0, 0)
cube.receiveShadow = true
this.parts.push(cube)
},
// 墙壁
wall(size, position){
let texture = new THREE.TextureLoader().load(require('@/assets/three/tile.jpg'));
texture.anisotropy = 4
let data = {
map: texture,
// color: 0x07313F,
transparent: true,
opacity: 1
}
let geometry = new THREE.BoxGeometry(size.x, size.y,size.z);
let material = new THREE.MeshLambertMaterial(data);
let cube = new THREE.Mesh(geometry, material);
cube.position.set(position.x, position.y, position.z)
this.scene.add(cube);
},
// 机柜
chartlet(x, y, z){
let map = new THREE.TextureLoader().load(require('@/assets/three/jigui.jpg'));
let group = new THREE.Mesh();
let mats = [];
mats.push(new THREE.MeshPhongMaterial({ map }));
mats.push(new THREE.MeshPhongMaterial({
color: 0x3C3B42
}));
mats.push(new THREE.MeshPhongMaterial({
color: 0x3C3B42
}));
mats.push(new THREE.MeshPhongMaterial({
color: 0x3C3B42
}));
mats.push(new THREE.MeshPhongMaterial({
color: 0x3C3B42
}));
mats.push(new THREE.MeshPhongMaterial({
color: 0x3C3B42
}));
let cubeGeom = new THREE.BoxBufferGeometry(15, 50, 30);
let cube = new THREE.Mesh(cubeGeom, mats);
cube.position.set(x, y, z)
group.add(cube);
this.scene.add(group)
},
// 空调
vavAair(x, y, z){
let map = new THREE.TextureLoader().load(require('@/assets/three/kt.png'));
let group = new THREE.Mesh();
let mats = [];
mats.push(new THREE.MeshPhongMaterial({ color: 0xffffff }));
mats.push(new THREE.MeshPhongMaterial({
color: 0xffffff
}));
mats.push(new THREE.MeshPhongMaterial({
color: 0xffffff
}));
mats.push(new THREE.MeshPhongMaterial({
color: 0xffffff
}));
mats.push(new THREE.MeshPhongMaterial({
color: 0xffffff
}));
mats.push(new THREE.MeshPhongMaterial({
map
}));
let cubeGeom = new THREE.BoxBufferGeometry(40, 15, 15);
let cube = new THREE.Mesh(cubeGeom, mats);
cube.position.set(x, y, z)
group.add(cube);
this.scene.add(group)
},
// 鼠标点击事件
mousedown(){
let raycaster = new THREE.Raycaster(); //光线投射,用于确定鼠标点击位置
let mouse1 = new THREE.Vector2()
let mouse2 = new THREE.Vector2()
let top = 69
window.addEventListener("pointerdown", (event) => {
mouse1.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse1.y = - ( (event.clientY - top) / window.innerHeight ) * 2 + 1;
});
window.addEventListener("pointerup", (event) => {
mouse2.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse2.y = - ( (event.clientY - top) / window.innerHeight ) * 2 + 1;
if(mouse1.x === mouse2.x && mouse1.y === mouse2.y){
//以camera为z坐标,确定所点击物体的3D空间位置
raycaster.setFromCamera(mouse1, this.camera);
//确定所点击位置上的物体数量
let intersects = raycaster.intersectObjects(this.scene.children);
//选中后进行的操作
if(intersects.length){
console.log(intersects)
// intersects[0].object.material.color.set( 0xff0000 );
}
}
});
},
// 引入模型 人物
mod(){
let that = this
let loader = new FBXLoader()
loader.load('three/SambaDancing.fbx', function(obj){
obj.scale.set(.35, .35, .35); // 放大缩小
obj.position.set(205, 0, -80); // 位置
obj.rotation.y += 1.55; // 旋转
that.scene.add(obj)
that.clock = new THREE.Clock()
// obj作为参数创建一个混合器,解析播放obj及其子对象包含的动画数据
that.mixer = new THREE.AnimationMixer(obj);
let animationAction = that.mixer.clipAction(obj.animations[0]);
// animationAction.timeScale = 1; //默认1,可以调节播放速度
// animationAction.loop = THREE.LoopOnce; //不循环播放
// animationAction.clampWhenFinished=true;//暂停在最后一帧播放的状态
animationAction.play(); //播放动画
}, undefined, function ( error ) {
console.error( error );
});
},
}
};
</script>
<style scoped>
body {
margin: 0;
padding: 0;
background-color: #000;
color: #fff;
font-family: Monospace;
font-size: 13px;
line-height: 24px;
overscroll-behavior: none;
}
#info {
position: absolute;
top: 0px;
width: 100%;
padding: 0;
box-sizing: border-box;
text-align: center;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
z-index: 1; /* TODO Solve this in HTML */
}
</style>
vue-three 基础模板
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 方便开发者快速搭建框架,现基于vue-element-admin为基础简化了功能,有需要的小伙伴可以自行下载使用,...
- 1.插值 1.1文本 {{msg}} 双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTM...
- 3、常用模板语法 官方文档 时间:2021年06月15日 15时58分15秒 Vue.js 使用了基于 HTML ...
- 前言 该项目跑了下 vue-cli 3.0.0 多页面项目创建的流程,就当个以后多页项目的雏形了,新版的 vue-...