在vue组件中导入并使用three.js库
Import and use three.js library in vue component
有人可以向我解释一下我如何正确 导入并在 vue 组件中使用 three.js 库吗?
经过多次搜索,我很清楚大多数人使用以下行在 vue 组件中导入 three.js,但是我认为它已经过时(用于较旧的 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...)
The complete Vue component file 我正在为我的项目使用。
您可以像这样使用 require 语句:
const THREE = require('THREE')
但一些插件假定 THREE
在 window 上可用,因此您可能想要 window.THREE = require('THREE')
我对 import 语句没有太多经验,但上面的应该有用。
适合只想尝试基本设置的任何人。这是 vue 组件 'ThreeTest' 中的 three.js 示例。使用 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>
这是对@PolygonParrot 之前给出的答案的跟进。由于评论长度的限制,我不得不把我的答案放在这里。
非常感谢您的回答,@PolygonParrot。这对我帮助很大!根据您的演示代码,我发现将动画代码与 Vue 组件代码分开的关键是将正确的动画上下文传递给 animation.js 中定义的模块。我认为我的第一次尝试失败可能是因为函数式编程的 "closure" 特性,对于像我这样的老程序员来说,这是一个很难适应的概念。我的 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 模板可以保持干净并将动画逻辑隐藏在视图后面。我认为我在这里使用上下文看起来仍然很奇怪,但至少它现在很好地满足了我的目的。
由于给出的答案对我不起作用,我将分享对我有用的初始设置。我在示例中使用 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>
感谢 Polygon Parrot 提供的模板,这正是我来这里寻找的。我想包含针对您的示例的 window resize 方法,只是为了让您的模板更完整一些。
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()})
}
import * as THREE from "three";
对我来说效果很好!
有人可以向我解释一下我如何正确 导入并在 vue 组件中使用 three.js 库吗?
经过多次搜索,我很清楚大多数人使用以下行在 vue 组件中导入 three.js,但是我认为它已经过时(用于较旧的 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...)
The complete Vue component file 我正在为我的项目使用。
您可以像这样使用 require 语句:
const THREE = require('THREE')
但一些插件假定 THREE
在 window 上可用,因此您可能想要 window.THREE = require('THREE')
我对 import 语句没有太多经验,但上面的应该有用。
适合只想尝试基本设置的任何人。这是 vue 组件 'ThreeTest' 中的 three.js 示例。使用 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>
这是对@PolygonParrot 之前给出的答案的跟进。由于评论长度的限制,我不得不把我的答案放在这里。
非常感谢您的回答,@PolygonParrot。这对我帮助很大!根据您的演示代码,我发现将动画代码与 Vue 组件代码分开的关键是将正确的动画上下文传递给 animation.js 中定义的模块。我认为我的第一次尝试失败可能是因为函数式编程的 "closure" 特性,对于像我这样的老程序员来说,这是一个很难适应的概念。我的 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 模板可以保持干净并将动画逻辑隐藏在视图后面。我认为我在这里使用上下文看起来仍然很奇怪,但至少它现在很好地满足了我的目的。
由于给出的答案对我不起作用,我将分享对我有用的初始设置。我在示例中使用 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>
感谢 Polygon Parrot 提供的模板,这正是我来这里寻找的。我想包含针对您的示例的 window resize 方法,只是为了让您的模板更完整一些。
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()})
}
import * as THREE from "three";
对我来说效果很好!