声明式开发Threejs(一)
介绍
上一篇我们搭建了vue+threejs的开发环境,并放在了一个组件中,但是这里有一个问题,就是这个是一个面向过程的开发,像vue组件都是声明式的开发,这样别人使用我们的组件的时候不太友好
声明式VS命令式
命令式:创建一个div(createElement),div里有一个text(inner),背景色红色( style.background)-- 需要我们对每一步进行操作
声明式:<div style="background-color: red;">111</div>
,只需要书写结果,并不需要关注怎么实现的
简单总结:因为我们很难写出完美代码,即使写出来了性价比也太低了,所以声明式是目前流行的
分析
在对上一节内容进行声明式封装之前,先简单分析一下,我们最终要实现出什么样子,下图是以前的写法,虽然很简单,但是也需要我们写这么多东西
有没有更简单的方式来完成呢,当然有就是声明式的封装,这样当再次使用的时候就非常简单了,我们先来看一下最基本的场景我们都需要什么
- 画布(canvas)
- 场景(Scene)
- 相机(Camera)
- 物体(geometry、注意:推荐BufferGeometry,性能优化)
- 刷新(fps)
如下图,我们只需要像vue一样,简单的使用几个标签就可以完成我们需求,而且别人使用起来也没什么心智负担
下面我们基于上图进行封装
搭建环境
pnpm create vite
然后对项目进行简单的整理一下
- 创建我们的画布
// src/components/MyCanvas.vue
<template>
<canvas
ref="canvasRef"
:style="{
display: 'block',
width: '100%',
height: '100%',
top: 0,
left: 0,
pointerEvents: 'auto',
touchAction: 'none',
}"
></canvas>
</template>
- 在App.vue中引入我们的画布
<script setup lang="ts">
import MyCanvas from './components/MyCanvas.vue'
</script>
<template>
<MyCanvas>
</MyCanvas>
</template>
<style scoped></style>
- 清理style.css样式
html,
body {
margin: 0;
padding: 0;
}
- 这个时候就可以看到页面上就已经有我们的画布了
MyCanvas
目前我们只是把canvas放在最外层了,还没有把WebGLRenderer和canvas关联起来
在这个组件中,我们有以下内容需要实现
- 渲染器 WebGLRenderer
- 场景 Scene
- 循环更新 render
把场景和画布传入一个函数
// 画布
const canvasRef = ref<HTMLCanvasElement>();
// 存储我们需要的上下文信息
const context = shallowRef<MyContext | null>(null);
// 场景
const scene = shallowRef(new Scene())
onMounted(() => {
const existingCanvas = canvasRef as Ref<HTMLCanvasElement>;
// useMyContextProvider 创建我们的3D场景
context.value = useMyContextProvider({
scene: scene.value,
canvas: existingCanvas,
});
});
import type { MaybeRef } from "vue";
import type { Scene } from "three";
export interface MyContext {
scene: Scene;
canvas: MaybeRef<HTMLCanvasElement>;
}
import { MyContext } from "./myInterface";
export function useMyContextProvider(params: MyContext) {
return params;
}
接下来我们就主要实现useMyContextProvider函数
转载自:https://juejin.cn/post/7366972839779958834