Javascript 在Vuetify.js组件中加载三个.js场景

Javascript 在Vuetify.js组件中加载三个.js场景,javascript,vue.js,vuejs2,three.js,vuetify.js,Javascript,Vue.js,Vuejs2,Three.js,Vuetify.js,我正在尝试将一个基本的Three.js场景加载到Vuetifyv-app组件中,但我似乎无法让它工作 使用vue、vue路由器和three js,因此消除Vuetify我在“Hello World”类型场景中加载时没有任何问题。如果您感兴趣,可以在此处找到此工作vuetify less尝试的代码 我已经尝试使用路由检测器在检测到试图加载/viewer时消除v-app组件(在组件中使用v-if),但结果最好是劣质的(与3D查看器重叠的ui,一个不分大小的3D查看器,每次重新加载的结果基本上不同)

我正在尝试将一个基本的
Three.js
场景加载到Vuetify
v-app
组件中,但我似乎无法让它工作

使用
vue
vue路由器
three js
,因此消除Vuetify我在“Hello World”类型场景中加载时没有任何问题。如果您感兴趣,可以在此处找到此工作vuetify less尝试的代码

我已经尝试使用路由检测器在检测到试图加载
/viewer
时消除
v-app
组件(在组件中使用
v-if
),但结果最好是劣质的(与3D查看器重叠的ui,一个不分大小的3D查看器,每次重新加载的结果基本上不同)

我的当前代码由
Navbar.vue
组件、
App.vue
Viewer.vue
视图组成。我还启用了
vue路由器
,该路由器按预期工作。 我目前正在使用的最小项目,试图让vuetify与Three.js一起工作:

Viewer.vue

<template>
  <div id="container"></div>
</template>

<script>
import * as THREE from "three";

export default {
  name: "ThreeTest",
  data() {
    return {
      cube: null,
      renderer: null,
      scene: null,
      camera: null,
    };
  },
  methods: {
    init: function () {
      this.scene = new THREE.Scene();
      this.camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );

      this.renderer = new THREE.WebGLRenderer();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(this.renderer.domElement);

      const geometry = new THREE.BoxGeometry(1, 1, 1);
      const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
      this.cube = new THREE.Mesh(geometry, material);
      this.scene.add(this.cube);

      this.camera.position.z = 5;

    },
    animate: function () {
      requestAnimationFrame(this.animate);

      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01;

      this.renderer.render(this.scene, this.camera);
    },
  },
  mounted() {
    this.init();
    this.animate();
  },
};
</script>

从“三”中导入*作为三;
导出默认值{
名称:“三个测试”,
数据(){
返回{
多维数据集:null,
渲染器:null,
场景:空,
摄像机:空,
};
},
方法:{
init:函数(){
this.scene=新的三个.scene();
this.camera=新的3.perspective相机(
75,
window.innerWidth/window.innerHeight,
0.1,
1000
);
this.renderer=new THREE.WebGLRenderer();
this.renderer.setSize(window.innerWidth、window.innerHeight);
document.body.appendChild(this.renderer.doElement);
const geometry=新的3.BoxGeometry(1,1,1);
const material=new THREE.MeshBasicMaterial({color:0x00ff00});
this.cube=新的三个网格(几何体、材质);
this.scene.add(this.cube);
这个.camera.position.z=5;
},
设置动画:函数(){
requestAnimationFrame(this.animate);
这个.cube.rotation.x+=0.01;
这个.cube.rotation.y+=0.01;
this.renderer.render(this.scene,this.camera);
},
},
安装的(){
this.init();
这个。动画();
},
};
导航栏

<template>
  <div>
    <v-app-bar app clipped-left flat dark>
      <v-toolbar-title>
        <span class="first-word font uppercase">stp</span>
        <span class="second-word font uppercase">upload</span>
      </v-toolbar-title>
      <v-spacer></v-spacer>
    </v-app-bar>

    <v-navigation-drawer app clipped flat dark expand-on-hover>
      <v-list>
        <v-list-item class="px-2">
          <v-list-item-avatar>
            <v-img src="https://randomuser.me/api/portraits/men/11.jpg"></v-img>
          </v-list-item-avatar>

          <v-list-item-title>
            <span class="username">{{ username }}</span>
          </v-list-item-title>
        </v-list-item>
        <v-list-item v-for="item in navbarlist" :key="item.route" :to="item.route">
          <v-list-item-icon>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-icon>
          <v-list-item-content>{{ item.text }}</v-list-item-content>
        </v-list-item>
      </v-list>

      <template v-slot:append>
        <v-list>
          <v-list-item @click="logout()">
            <v-list-item-icon>
              <v-icon color="red">mdi-logout</v-icon>
            </v-list-item-icon>
            <v-list-item-content>Logout</v-list-item-content>
          </v-list-item>
        </v-list>
      </template>
    </v-navigation-drawer>
  </div>
</template>

<script>
export default {
  data: () => ({
    drawer: true,
    navbarlist: [
      { icon: "mdi-view-dashboard", text: "Dashboard", route: "/" },
      { icon: "mdi-upload", text: "Upload", route: "/upload" },
      { icon: "mdi-video-3d", text: "Viewer", route: "/viewer" },
    ],
    username: "",
  }),
  created: function () {
    this.username = this.$store.state.userProfile.name;
  },
  methods: {
    logout() {
      this.$store.dispatch("logout", {});
    },
  },
};
</script>

<style>
.font {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
    Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
.uppercase {
  text-transform: uppercase;
}
.first-word {
  font-weight: 400;
}
.second-word {
  font-weight: 200;
  color: grey;
}
.item-tile-icon {
  color: black;
}
.username {
  color: whitesmoke;
  font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
  font-weight: lighter;
  letter-spacing: 0.001em;
}
</style>

stp
上传
{{username}}
{{item.icon}
{{item.text}
mdi注销
注销
导出默认值{
数据:()=>({
抽屉:是的,
导航栏列表:[
{图标:“mdi视图仪表板”,文本:“仪表板”,路径:“/”},
{图标:“mdi上传”,文本:“上传”,路由:“/upload”},
{图标:“mdi-video-3d”,文本:“查看器”,路径:“/Viewer”},
],
用户名:“”,
}),
已创建:函数(){
this.username=this.$store.state.userProfile.name;
},
方法:{
注销(){
这是.store.dispatch(“注销”{});
},
},
};
.font{
字体系列:-苹果系统、BlinkMacSystemFont、“Segoe UI”、机器人、氧气、,
Ubuntu,坎塔雷尔,“开放式Sans”,“Helvetica Neue”,无衬线;
}
.大写字母{
文本转换:大写;
}
.第一个字{
字体大小:400;
}
.第二个字{
字号:200;
颜色:灰色;
}
.项目平铺图标{
颜色:黑色;
}
.用户名{
颜色:白烟;
字体系列:“富兰克林哥特式中”、“Arial窄”、Arial、无衬线;
字体重量:较轻;
字母间距:0.001em;
}
App.vue

<template>
  <div>
    <v-app>
      <Navbar v-if="showNavBar"/>
      <v-main>
        <router-view></router-view>
      </v-main>
    </v-app>
  </div>
</template>

<script>
import Navbar from "./components/Navbar";

export default {
  name: "App",

  components: {
    Navbar,
  },

  data: () => ({
    showNavBar: true,
    app: true
  }),
  mounted() {
    }
};
</script>


从“/components/Navbar”导入导航栏;
导出默认值{
名称:“应用程序”,
组成部分:{
导航栏,
},
数据:()=>({
showNavBar:是的,
app:true
}),
安装的(){
}
};

如果我积极帮助用户,我不知道为什么人们会热衷于删除我的答案。如果我不能评论,我不能评论,我的规则不是我必须有声誉才能发表评论,而是必须写一个答案

关于这个问题:

您需要将dom元素不是附加到document.body,而是附加到vue组件中的实际div

因此,不是:

document.body.appendChild(this.renderer.domElement);
请使用:

document.getElementById('container').appendChild(this.renderer.domElement);