「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战」
背景
去年之所以再次兴起了学习 WebGL 的念头,主要是有两个原因:
- 其一是现阶段元宇宙概念巨火;
- 其二是想用 Web 技术实现游戏和3D动画场景,比如头号玩家电影中的科幻场景,或者像宫崎骏的动漫中的场景,简直酷毙了。
技术
vue3.0
typescript
- threejs
实现
创建一个项目
用 ue-cli 可以快速的创建一个项目,我本地已经创建好了如下:
引入 threejs
因为我们用typescript
,所以我们引入@types/three
要看@types/three文档可以去
npm: www.npmjs.com/package/@ty…
github: github.com/DefinitelyT…
安装threejs
npm install --save @types/three
安装好的效果,如下
应用threejs
在我们要用得项目中引入three
import * as THREE from "three";
引入后我们发现报错,解决如下:在shims-vue.d.ts
文件中加入
declare module "@types/three";
写个demo
- 在router/index.ts增加路由,代码如下:
{
path: "/demo01",
name: "Demo01",
component: () => import("@/views/Demo01/Demo01.vue"),
}
2. 在views中增加目录,如下:
- demo01.vue代码:
<template>
<div class="demo"></div>
</template>
<script lang="ts">
import ThreeJs from "./index";
import { defineComponent, onMounted } from "vue";
export default defineComponent({
name: "Demo01",
props: {},
setup() {
onMounted(() => {
new ThreeJs();
});
},
});
</script>
<style scoped lang="scss"></style>
- index.ts 代码,如下:
import * as THREE from "three";
export default class ThreeJs {
scene: THREE.Scene | null = null;
camera: THREE.PerspectiveCamera | null = null;
renderer: THREE.WebGLRenderer | null = null;
ambientLight: THREE.AmbientLight | null = null;
mesh: THREE.Mesh | null = null;
constructor() {
this.init();
}
init(): void {
// 第一步新建一个场景
this.scene = new THREE.Scene();
this.setCamera();
this.setRenderer();
this.setCube();
this.animate();
}
// 新建透视相机
setCamera(): void {
// 第二参数就是 长度和宽度比 默认采用浏览器 返回以像素为单位的窗口的内部宽度和高度
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this.camera.position.z = 5;
}
// 设置渲染器
setRenderer(): void {
this.renderer = new THREE.WebGLRenderer();
// 设置画布的大小
this.renderer.setSize(window.innerWidth, window.innerHeight);
//这里 其实就是canvas 画布 renderer.domElement
document.body.appendChild(this.renderer.domElement);
}
// 设置环境光
setLight(): void {
if (this.scene) {
this.ambientLight = new THREE.AmbientLight(0xffffff); // 环境光
this.scene.add(this.ambientLight);
}
}
// 创建网格模型
setCube(): void {
if (this.scene) {
const geometry = new THREE.BoxGeometry(); //创建一个立方体几何对象Geometry
// const material = new THREE.MeshBasicMaterial({ color: 0xff3200 }); //材质对象Material
const texture = new THREE.TextureLoader().load(
"/assets/imgs/dalishi.jpg"
); //首先,获取到纹理
const material = new THREE.MeshBasicMaterial({ map: texture }); //然后创建一个phong材质来处理着色,并传递给纹理映射
this.mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
this.scene.add(this.mesh); //网格模型添加到场景中
this.render();
}
}
// 渲染
render(): void {
if (this.renderer && this.scene && this.camera) {
this.renderer.render(this.scene, this.camera);
}
}
// 动画
animate(): void {
if (this.mesh) {
requestAnimationFrame(this.animate.bind(this));
this.mesh.rotation.x += 0.01;
this.mesh.rotation.y += 0.01;
this.render();
}
}
}
- 看效果: