这次是真的被迫营业,原本打算五天做好的东西,三天做好还部署好上交了,感谢React-three-fiber和netlify。
大致就是离校一个月了,疫情原因回不去,导师自然会催催进度,赶巧的是那天是我准备为他干活的前一天。满口应允下来,原本五天的空闲时间一下就缩成了三天,还要部署好,还要能给他看。
这个过程主要运用到了react-three-fiber框架,这是一个基于React Hooks和Three.js的web GL框架,还是很好用的,有用的API其实有很多,时间原因我也没有看太多,只用到了最基础的useFrame和几个基础的geometry、texture。
最后我其实真不觉得这个仿真系统有啥用,
关于这个框架因为我还没有摸熟,很多东西都是靠着逻辑硬做的,研究深了可能会有些收获。其次这个框架中很大的一部分是可以用Three.js取代的,因为他其实只是使用React逻辑将很多元素从canvas里面分离出来而已。
先看个小demo给没有接触过three.js的开发者找点感觉:
import ReactDOM from 'react-dom'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from 'react-three-fiber'
function Box(props) {
const mesh = useRef()
const [hovered, setHover] = useState(false)
const [active, setActive] = useState(false)
useFrame(() => (mesh.current.rotation.x = mesh.current.rotation.y += 0.01))
return (
<mesh
{...props}
ref={mesh}
scale={active ? [1.5, 1.5, 1.5] : [1, 1, 1]}
onClick={e => setActive(!active)}
onPointerOver={e => setHover(true)}
onPointerOut={e => setHover(false)}>
<boxBufferGeometry attach="geometry" args={[1, 1, 1]} />
<meshStandardMaterial attach="material" color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
ReactDOM.render(
<Canvas>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
</Canvas>,
document.getElementById('root')
)
简单讲一下这段浓重的React风格的代码,mesh作为可以负载到canvas上的元素,是渲染模型等的唯一载体,一个简单的mesh如图所示,主要需要注意的就是下面这两段:
<boxBufferGeometry attach="geometry" args={[1, 1, 1]} />
<meshStandardMaterial attach="material" color={hovered ? 'hotpink' : 'orange'}
一个定义了geometry,我们可以理解为物体,形状之类的,一个是material,即这个物体的材质。
这里通过useRef()取到mesh并通过useFrame让其渲染,如上代码即让box这个mesh不断旋转。
使用过three.js的朋友应该知道,在canvas上面检查元素,添加点击事件等其实都是比较麻烦的,能够和最新的web GL结合的框架更是少之又少,大部分工程化构建都是通过ts start来实现的,而react-three-fiber借助react-spring社区的东风,加上可以直接通过create-react-app这个优秀的脚手架进行创建,因此在国外的three.js开发中一直都是很受欢迎的。
上段代码也显示,我们在mesh元素上添加动作是很容易的,当然这只是我学艺不精的肤浅了解,对这个框架的几个钩子函数或Three.jsAPI更熟悉的人应该更能发现其中的优点。
当然这个框架不是完美的,其中一个很尴尬的问题就是Redux的问题。简单的讲,即使我们用Provider完美的包裹了Canvas(注意这个canvas的C是大写的,他是react-three-fiber的一个元素,而不是H5的canvas),我们仍然不能在canvas中内部的任意mesh里面使用UseSelector等react-redux的API。
关于这一点目前主要有两种解决办法,一个是通过rustand这个react-spring推荐的状态管理框架解决,它提供了更契合react-three-fiber框架的解决方案。
同时它的一些API和Redux还是有点像的,反正我是没用,但不代表以后不用。
第二种就是在Canvas外拿到数据,然后用props传值进去,虽然周转麻烦了点,但是用起来倒还好,毕竟我的那个仿真系统除了canvas外也有很多逻辑和数据要处理,行吧其实还是redux生态习惯了之后不喜欢别的。
部署的问题,原本不是问题,create-react-app打包会生成一个build文件夹,一般来说我们直接把这个文件夹拖到netlify或者zeit-to之后,他自然就会使用服务器给我们部署好,域名什么的添加起来也特别简单,比如Github Students有一项权益,有免费一年的name.com的一个免费域名。
问题就是网速呀,netlify加上name.com的域名,足够让我这个附加WebGL技术的网站加载个几分钟了,如果没有FQ的话。
但是因为使用到了react-router-dom,也不能就直接打开index.html,因此目前的方案主要有两个,一个是通过github pages和github actions,使用node.js服务,但是失败了。这个是后话,涉及CICD,我们后面再聊。
另一个就是用自己的服务器呗,其实这是最简单的,无非加个docker,nginx多解析一项,但是因为我自己的网站部署在这里,就很不想把这个个人服务器充公。
继续纠结中。
网站就不放了,涉及毕设,等我明年毕业吧