Загрузите сцену Three. js в компонент Vuetify. js - PullRequest
1 голос
/ 04 августа 2020

Я пытаюсь загрузить базовую c Three.js сцену в компонент Vuetify v-app, но не могу заставить ее работать.

Используя vue, vue-router и three-js, поэтому, исключив Vuetify, у меня не возникнет проблем с загрузкой в ​​сцене типа «Hello World». Если вам интересно, код для этой рабочей попытки vuetify-less можно найти здесь https://github.com/TjalleWired/vue-three-test

Я уже пробовал использовать детектор маршрута для устранения компонента v-app, когда он обнаруживает, что /viewer пытается быть загружен (используя v-if в компонентах), но результаты в лучшем случае плохие (перекрытие пользовательского интерфейса с программой трехмерного просмотра, исчезающее средство трехмерного просмотра, в основном разные результаты при каждой перезагрузке).

Мой текущий код состоит из компонента Navbar.vue, App.vue и вида Viewer.vue. Я также включил vue-router, который работает как задумано. Минимальный проект, который я сейчас использую, пытаясь заставить vuetify работать с 3. js: https://github.com/TjalleWired/three-vuetify/

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>

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

1 Ответ

1 голос
/ 07 августа 2020

Я не уверен, почему люди стремятся удалить мой ответ, если я конструктивно пытаюсь помочь пользователю. Если я не могу комментировать, я не могу комментировать, это не мое правило, что я должен иметь репутацию, чтобы оставить комментарий, и вместо этого я должен написать ответ ...

К проблеме:

вам нужно прикрепить элемент dom не к document.body, а к фактическому div внутри вашего vue компонента.

Поэтому вместо:

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

Используйте:

document.getElementById('container').appendChild(this.renderer.domElement);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...