繁体   English   中英

在 Vuetify.js 组件中加载 Three.js 场景

[英]Load Three.js scene in Vuetify.js component

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

使用vuevue-routerthree-js ,因此消除了 Vuetify 我在“Hello World”类型的场景中加载完全没有问题。 如果您有兴趣,可以在此处找到此工作的 vuetify-less 尝试的代码https://github.com/TjalleWired/vue-three-test

我已经尝试使用路由检测器来消除v-app组件,当它检测到/viewer正在尝试加载时(在组件中使用v-if ),但结果充其量是粗制滥造的(与 3D 重叠 ui查看器,一个令人失望的 3d 查看器,每次重新加载的结果基本不同)。

我当前的代码包含一个Navbar.vue组件、 App.vue和一个Viewer.vue视图。 我还启用了按预期工作的vue-router 我目前正在使用的最小项目试图让 vuetify 与 Three.js 一起工作: https://github.com/TjalleWired/three-vuetify/

查看器.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>

导航栏.vue

<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>

应用程序.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>

如果我正在建设性地尝试帮助用户,我不确定为什么人们热衷于删除我的答案。 如果我不能评论,我不能评论,我的规则不是我必须有声誉才能发表评论,而是必须写一个答案......

问题:

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

因此,而不是:

document.body.appendChild(this.renderer.domElement);

请用:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM