WedX - журнал о программировании и компьютерных науках

Импорт и использование библиотеки three.js в компоненте vue

Может ли кто-нибудь объяснить мне, как правильно импортировать и использовать библиотеку three.js в компоненте vue?

После многих поисков мне стало ясно, что большинство людей используют следующую строку для импорта three.js в компонент vue, однако я думаю, что она устарела (usef для более старого документа three.js или используется в более старом vue-версии).

import * as THREE from './js/three.js';

К сожалению, это не работает для меня, так как я получаю следующие предупреждения при последующей компиляции моего проекта vue. (Обратите внимание, что проект на самом деле не компилируется правильно, и я получаю пустой файл при переходе к нему). введите описание изображения здесь

Я пробовал много других распространенных способов импорта three.js, которые тоже не работали!

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

exports.WebGLRenderTargetCube = WebGLRenderTargetCube;
exports.WebGLRenderTarget = WebGLRenderTarget;
exports.WebGLRenderer = WebGLRenderer;
exports.ShaderLib = ShaderLib;
exports.UniformsLib = UniformsLib;
exports.UniformsUtils = UniformsUtils;
exports.ShaderChunk = ShaderChunk;
exports.FogExp2 = FogExp2;
exports.Fog = Fog;
exports.Scene = Scene;
(and so one...)


Полный файл компонента Vue, который я использую для своего проекта.


Ответы:


1

Вы можете использовать оператор require следующим образом:

const THREE = require('THREE')

Но некоторые плагины предполагают, что THREE доступно в окне, поэтому вы можете сделать window.THREE = require('THREE')

У меня нет большого опыта работы с операторами импорта, но вышеизложенное должно работать.

16.12.2017

2

Для тех, кто просто хочет попробовать базовую настройку. Это пример three.js в компоненте vue «ThreeTest». Настройка проекта с помощью vue-cli 'vue init webpack ProjectName', 'cd ProjectName', 'npm install three --save' и замените компонент HelloWorld на этот:

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

<script>
import * as Three from 'three'

export default {
  name: 'ThreeTest',
  data() {
    return {
      camera: null,
      scene: null,
      renderer: null,
      mesh: null
    }
  },
  methods: {
    init: function() {
        let container = document.getElementById('container');

        this.camera = new Three.PerspectiveCamera(70, container.clientWidth/container.clientHeight, 0.01, 10);
        this.camera.position.z = 1;

        this.scene = new Three.Scene();

        let geometry = new Three.BoxGeometry(0.2, 0.2, 0.2);
        let material = new Three.MeshNormalMaterial();

        this.mesh = new Three.Mesh(geometry, material);
        this.scene.add(this.mesh);

        this.renderer = new Three.WebGLRenderer({antialias: true});
        this.renderer.setSize(container.clientWidth, container.clientHeight);
        container.appendChild(this.renderer.domElement);

    },
    animate: function() {
        requestAnimationFrame(this.animate);
        this.mesh.rotation.x += 0.01;
        this.mesh.rotation.y += 0.02;
        this.renderer.render(this.scene, this.camera);
    }
  },
  mounted() {
      this.init();
      this.animate();
  }
}
</script>

<style scoped>
    //TODO give your container a size.
</style>
15.03.2018
  • Спасибо! Искал что-то подобное, попробую, если получится :) 22.03.2018
  • Работал нормально! Требовались некоторые корректировки, чтобы он работал для компонента, который не является единственным дочерним элементом тела, но предложил это как редактирование этого кода. 22.03.2018
  • ИМО, этот ответ должен быть принятым. Там намного подробнее и понятнее. 07.08.2018
  • Но когда я попытался разделить функции init и animate из файла .vue в другой файл .js, чтобы секция сценария моего vue-файла была более концентрированной, я ничего не отображал на экране. Из журналов консоли я могу сказать, что мои функции init() и animate() вызываются ядром three.js, а моя функция анимации получила правильный результат инициализации от предыдущего вызова init. Я довольно зеленый для программирования Vue, поэтому любая идея указать, что не так с моим случаем, будет оценена. 06.12.2018
  • @ L3w1s L3w1s Поскольку я не знаю, что вы пробовали, я даю вам быстрое и грязное решение для анимации. Код следует использовать только для тестирования ;) Важно, чтобы в анимации был нужен тот контекст, который был создан в функции инициализации: animation.js let context; function set(c) { context = c; }; let animate = function animate() { requestAnimationFrame(animate); context.mesh.rotation.x += 0.01; context.mesh.rotation.y += 0.02; context.renderer.render(context.scene, context.camera); }; export { animate, set }; -> следующий комментарий 06.12.2018
  • Расширение файла vue: import * as animations from './animate.js' mounted() { this.init(); animations.set({camera: this.camera, scene: this.scene, renderer: this.renderer, mesh: this.mesh}); animations.animate(); } 06.12.2018
  • Мне пришлось добавить эти строки кода CSS в мой App.vue, потому что высота моего холста была 0: canvas { width: 100%; height: 100% } 22.05.2019
  • Пришлось добавить: <style scoped> #container { height: 200px; } </style> 16.12.2019
  • Как вы гарантируете, что приведенный выше скрипт не вызывается каждый раз, когда часть threejs выходит за рамки? - я считаю, что vue уничтожает детей, когда они выходят из поля зрения. Было бы дорого воссоздавать 3D-вид каждый раз, например, когда пользователь щелкает между вкладками. 21.01.2021

  • 3

    Поскольку данные ответы не сработали для меня, я поделюсь начальной настройкой, которая сработала для меня. В моем примере я использую Nuxt.js.

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

    введите здесь описание изображения

    <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
    
          const animate = function() {}
        },
        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>
    
    10.06.2019

    4

    Это продолжение предыдущего ответа, данного @PolygonParrot. Из-за ограничения длины комментария мне пришлось поместить свой ответ здесь.

    Большое спасибо за ваш ответ, @PolygonParrot. Это мне очень помогло! Основываясь на вашем демонстрационном коде, я понял, что ключом к отделению кода анимации от кода компонента Vue является передача правильного контекста анимации в модуль, определенный в animation.js. Я думаю, что моя первая попытка не удалась, возможно, из-за функции «замыкания» функционального программирования, которая является болезненной концепцией для адаптации такого древнего программиста, как я. Мой animation.js теперь выглядит так:

    import * as THREE from 'three'
    // passed in container id within which this animation will be shown
    export function createBoxRotationContext(container) {
    var ctx = new Object();
    ctx.init = function init() {
        ctx.container = container;
        ctx.camera = new THREE.PerspectiveCamera(70, ctx.container.clientWidth/ctx.container.clientHeight, 0.01, 10);
        ctx.camera.position.z = 1;
    
        ctx.scene = new THREE.Scene();
    
        let geometry = new THREE.BoxGeometry(0.3, 0.4, 0.5);
        let material = new THREE.MeshNormalMaterial();
        ctx.box = new THREE.Mesh(geometry, material);
    
        ctx.fnhelper   = new THREE.FaceNormalsHelper(ctx.box, 0.3, 0x0000ff, 0.1);
        ctx.axes = new THREE.AxesHelper(5);
    
        ctx.scene.add(ctx.box);
        ctx.scene.add(ctx.axes);
        ctx.scene.add(ctx.fnhelper);
    
        ctx.renderer = new THREE.WebGLRenderer({antialias: true});
        ctx.renderer.setSize(ctx.container.clientWidth, ctx.container.clientHeight);
        ctx.container.appendChild(ctx.renderer.domElement);
    },
    ctx.animate = function animate() {
        requestAnimationFrame(animate);
        ctx.box.rotation.x += 0.01;
        ctx.box.rotation.y += 0.02;
        ctx.fnhelper.update();
        ctx.renderer.render(ctx.scene, ctx.camera);
    }
    return ctx;
    };
    

    И файл .vue теперь выглядит так:

    <script>
    import * as animator from '@/components/sandbox/animation.js'
    
    export default {
        name: 'Sandbox',
        data() {
          return {
            camera: null,
            scene: null,
            renderer: null,
            mesh: null
          }
        },
        mounted() {
            let context = animator.createBoxRotationContext(
                document.getElementById('three-sandbox')
            );
            context.init();
            context.animate();
        }
    }
    </script\>
    

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

    07.12.2018

    5
    import * as THREE from "three";
    

    Работал хорошо для меня!

    09.10.2020

    6

    Спасибо Polygon Parrot за ваш шаблон, это то, что я искал здесь. Я хотел бы включить метод изменения размера окна, специфичный для вашего примера, просто чтобы сделать ваш шаблон немного более полным.

    methods:{ ...
    onWindowResize(){
            this.renderer.setSize(window.innerWidth, window.innerHeight);
            this.camera.aspect = window.innerWidth / window.innerHeight;
            this.camera.updateProjectionMatrix()
        }
    
    created(){
            window.addEventListener('resize', () => {this.onWindowResize()})
      }
    
    25.01.2020
    Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]