123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- <template>
- <div class="three-model" @click="clickEvent">
- <loading ref="pageLoading"></loading>
- </div>
- </template>
- <script>
- import loading from '@com/coms/loading/loading.vue';
- import * as THREE from "three";
- import { GLTFLoader } from "@node/three/examples/jsm/loaders/GLTFLoader.js";
- import { OrbitControls } from "@node/three/examples/jsm/controls/OrbitControls.js";
- let camera, scene, renderer, controls;
- let mixers = [];
- let clock = new THREE.Clock();
- let fanAnimates = [];
- export default {
- // 名称
- name: "ThreeModel",
- // 使用组件
- components: {
- loading
- },
- // 传入参数
- props: {},
- // 自定义事件
- emits: {
- when: null,
- },
- // 数据
- data() {
- return {
- // 场景
- initScene: function () {
- scene = new THREE.Scene();
- // scene.background = new THREE.Color(0xa0a0a0);
- },
- // 相机
- initCamera: function () {
- camera = new THREE.PerspectiveCamera(45, this.$el.scrollWidth / this.$el.scrollHeight, 0.1, 10000);
- camera.position.set(50, 60, 50);
- },
- // 坐标轴
- initAxesHelper: function () {
- const axesHelper = new THREE.AxesHelper(150);
- scene.add(axesHelper);
- axesHelper.position.set(0, 0, 0);
- },
- // 渲染器
- initRender: function () {
- renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
- // renderer.setClearAlpha(0);
- renderer.setSize(this.$el.scrollWidth, this.$el.scrollHeight);
- this.$el.append(renderer.domElement);
- },
- // 灯光
- initLight: function () {
- // let light = new THREE.PointLight(0xffffff, 2);
- let light = new THREE.AmbientLight(0xffffff, 4);
- // light.position.set(50, 50, 50);
- scene.add(light);
- },
- // 控制器
- initControls: function () {
- controls = new OrbitControls(camera, renderer.domElement);
- },
- // 初始化一个风机动画
- initFanAnimate: function (fan1, fan2, fan3) {
- let fanAnimateObj = {
- speed: 0.05,
- fan1: fan1,
- fan2: fan2,
- fan3: fan3,
- };
- let fanAnimateFunction = function () {
- fanAnimateObj.fan1.rotateZ(fanAnimateObj.speed);
- fanAnimateObj.fan2.rotateZ(fanAnimateObj.speed);
- fanAnimateObj.fan3.rotateZ(fanAnimateObj.speed);
- fanAnimateObj.animateId = window.requestAnimationFrame(fanAnimateFunction);
- }
- fanAnimateObj.stop = function () {
- window.cancelAnimationFrame(fanAnimateObj.animateId);
- };
- fanAnimateObj.start = function () {
- fanAnimateFunction();
- };
- fanAnimateFunction();
- fanAnimates.push(fanAnimateObj);
- return fanAnimateObj;
- },
- // 清空风机动画
- clearFanAnimate: function () {
- while (fanAnimates.length > 0) {
- let fanAnimateObj = fanAnimates.shift();
- fanAnimateObj.stop();
- }
- },
- // 内容
- initContent: function () {
- // 加载3D地面
- let loaderGround = new GLTFLoader();/*实例化加载器*/
- loaderGround.load("static/3d/group/ng.gltf", (gltf) => {
- gltf.scene.position.set(5, 10, 0);
- scene.add(gltf.scene);
- // 找到一个大风扇的 Object3D
- let fanBig1_1 = gltf.scene.children[0].getObjectByName("Box707");
- let fanBig1_2 = gltf.scene.children[0].getObjectByName("Box708");
- let fanBig1_3 = gltf.scene.children[0].getObjectByName("Box709");
- let fanBig2_1 = gltf.scene.children[0].getObjectByName("Box719");
- let fanBig2_2 = gltf.scene.children[0].getObjectByName("Box720");
- let fanBig2_3 = gltf.scene.children[0].getObjectByName("Box721");
- let fanBig3_1 = gltf.scene.children[0].getObjectByName("Box699");
- let fanBig3_2 = gltf.scene.children[0].getObjectByName("Box701");
- let fanBig3_3 = gltf.scene.children[0].getObjectByName("Box702");
- this.initFanAnimate(fanBig1_1, fanBig1_2, fanBig1_3);
- this.initFanAnimate(fanBig2_1, fanBig2_2, fanBig2_3);
- this.initFanAnimate(fanBig3_1, fanBig3_2, fanBig3_3);
- let mixer = new THREE.AnimationMixer(gltf.scene.children[0]);
- mixer.clipAction(gltf.animations[0]).setDuration(3).play();
- mixers.push(mixer);
- console.log(gltf)
- }, (xhr) => {
- if (xhr.loaded == xhr.total) {
- this.$emit("when");
- setTimeout(() => {
- this.$refs.pageLoading.hide();
- }, 3000);
- }
- }, function (error) {
- console.error('load error!'+error.getWebGLErrorMessage());
- })
- },
- // 创建一个圆柱
- initCylinderGeometry: function () {
- let geometry = new THREE.CylinderGeometry(4, 4, 4, 64);
- let materials = [
- //圆柱侧面材质,使用纹理贴图
- new THREE.MeshBasicMaterial({
- color: 0xffff00,
- side: THREE.DoubleSide,
- transparent: true
- }),
- //圆柱顶材质
- new THREE.MeshBasicMaterial({
- transparent: true,
- opacity: 0,
- side: THREE.DoubleSide
- }),
- //圆柱底材质
- new THREE.MeshBasicMaterial({
- transparent: true,
- opacity: 0,
- side: THREE.DoubleSide
- })
- ];
- let cylinder = new THREE.Mesh(geometry, materials);
- scene.add(cylinder);
- },
- // 点击事件
- clickEvent: function (event) {
- event.preventDefault();
- let vector = new THREE.Vector3(
- (event.clientX / window.innerWidth) * 2 - 1,
- -(event.clientY / window.innerHeight) * 2 + 1,
- 0.5
- );
- vector = vector.unproject(camera);
- let raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
- let intersects = raycaster.intersectObjects(scene.children,true);
- console.log(intersects)
- // this.initCylinderGeometry();
- },
- // 初始化
- initThree: function () {
- this.initScene();
- // this.initAxesHelper();
- this.initCamera();
- this.initRender();
- this.initLight();
- this.initControls();
- this.initContent();
- renderer.setAnimationLoop(this.animate);
- },
- // 动画
- animate: function () {
- var delta = clock.getDelta();
- for ( var i = 0; i < mixers.length; i ++ ) { // 重复播放动画
- mixers[ i ].update( delta );
- }
- renderer.render(scene, camera);
- },
- };
- },
- // 函数
- methods: {},
- // 生命周期钩子
- beforeCreate() {
- // 创建前
- },
- created() {
- // 创建后
- },
- beforeMount() {
- // 渲染前
- },
- mounted() {
- // 渲染后
- this.initThree();
- },
- beforeUpdate() {
- // 数据更新前
- },
- updated() {
- // 数据更新后
- },
- beforeUnmount() {
- // 销毁前
- renderer.setAnimationLoop(null);
- camera = null;
- scene = null;
- renderer = null;
- },
- };
- </script>
- <style lang="less" scoped>
- .three-model {
- }
- </style>
|