likes
comments
collection
share

声明式开发Threejs(一)

作者站长头像
站长
· 阅读数 40

介绍

上一篇我们搭建了vue+threejs的开发环境,并放在了一个组件中,但是这里有一个问题,就是这个是一个面向过程的开发,像vue组件都是声明式的开发,这样别人使用我们的组件的时候不太友好

声明式VS命令式

命令式:创建一个div(createElement),div里有一个text(inner),背景色红色( style.background)-- 需要我们对每一步进行操作

声明式:<div style="background-color: red;">111</div>,只需要书写结果,并不需要关注怎么实现的

简单总结:因为我们很难写出完美代码,即使写出来了性价比也太低了,所以声明式是目前流行的

分析

在对上一节内容进行声明式封装之前,先简单分析一下,我们最终要实现出什么样子,下图是以前的写法,虽然很简单,但是也需要我们写这么多东西

声明式开发Threejs(一)

有没有更简单的方式来完成呢,当然有就是声明式的封装,这样当再次使用的时候就非常简单了,我们先来看一下最基本的场景我们都需要什么

  • 画布(canvas)
  • 场景(Scene)
  • 相机(Camera)
  • 物体(geometry、注意:推荐BufferGeometry,性能优化)
  • 刷新(fps)

如下图,我们只需要像vue一样,简单的使用几个标签就可以完成我们需求,而且别人使用起来也没什么心智负担

声明式开发Threejs(一)

下面我们基于上图进行封装

搭建环境

pnpm create vite

声明式开发Threejs(一)

然后对项目进行简单的整理一下

  • 创建我们的画布
// 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>

声明式开发Threejs(一)

  • 在App.vue中引入我们的画布
<script setup lang="ts">
import MyCanvas from './components/MyCanvas.vue'
</script>

<template>
  <MyCanvas>


  </MyCanvas>
</template>

<style scoped></style>

声明式开发Threejs(一)

  • 清理style.css样式
html,
body {
  margin: 0;
  padding: 0;
}

声明式开发Threejs(一)

  • 这个时候就可以看到页面上就已经有我们的画布了

声明式开发Threejs(一)

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,
  });
});

声明式开发Threejs(一)

import type { MaybeRef } from "vue";
import type { Scene } from "three";

export interface MyContext {
  scene: Scene;
  canvas: MaybeRef<HTMLCanvasElement>;
}

声明式开发Threejs(一)

import { MyContext } from "./myInterface";
export function useMyContextProvider(params: MyContext) {
  return params;
}

声明式开发Threejs(一)

接下来我们就主要实现useMyContextProvider函数

转载自:https://juejin.cn/post/7366972839779958834
评论
请登录