3

Rollup作者新作: Svelte Cubed, 拥抱 Three.js !

 2 years ago
source link: https://segmentfault.com/a/1190000041096792
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Rollup作者新作: Svelte Cubed, 拥抱 Three.js !

在2021年11月20日,Svelte 召开了第四次虚拟会议。

image-20211130233913710

而会议中最令我眼前一新的当然是 轮子哥 Rich-Harris 带来的 Svelte Cubed 了。

科普:轮子哥 Rich-Harris:Svelte、Rollup 作者

image-20211130234212172

这个项目亮眼的地方,并不是因为其他的演讲者不好,也并不是因为轮子哥是 Svelte 作者的原因。而是因为他带来的 Svelte-Cubed 和我目前在公司负责项目的技术栈有非常相似的感觉。在公司由于需要开发一个 新 的 H5 项目,因此我采用了较为激进的 Svelte + Aframe/Three.js + Tailwind.css + Vite 的组合。整套组合下来,无论是开发体验还是最后生产包的体积都非常的美妙~ 因此当我看到 轮子哥发布这个 新轮子 的时候,我无比激动,居然把我想要的组合直接集成到了 Svelte

然后我们来看看 Svelte-Cubed 面貌:

打开 https://svelte-cubed.vercel.app/ ,目前官网没有用自定义的域名,直接用了 vercel 的域名,猜测和 轮子哥去了 vercel 工作有关系。

image-20211201000056451

我们来看看 cubed 官方的一些示例:

2021-12-01-13.24.37

我们来尝试一下自己写一个项目,首先初始化一个 svelte 项目

npm init svelte@next my-new-app
cd my-new-app
npm install
npm run dev

安装 Three.js 和 svelte-cubed

npm install three svelte-cubed

如果使用 TypeScript ,还需要引入 Three.js 的 ts 声明

npm install -D @types/three

打开 src/routes/index.svelte

<script>
    import * as THREE from 'three';
    import * as SC from 'svelte-cubed';
</script>

<SC.Canvas>
    <SC.Mesh geometry={new THREE.BoxGeometry()} />
    <SC.PerspectiveCamera position={[1, 1, 3]} />
</SC.Canvas>

然后运行 npm run dev

image-20211201134014871

然后就报错了,通过查询,大概是因为没有设置一个 vite 选项。

打开 svelte.config.js ,加入关旭 vite ssr 的选项即可解决。

import adapter from '@sveltejs/adapter-auto';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    kit: {
        adapter: adapter(),

        // hydrate the <div id="svelte"> element in src/app.html
        target: '#svelte',
        vite: {
            ssr: {
                noExternal: ["three"]
            }
        }
    }
};

export default config;

image-20211201135911003

我们的项目就被运行起来了。

官方也明确说了,不会对 Three.js 对象进行包装,而是直接使用 Three.js 去创建并设置对象,因此需要在代码中引入 Three.js ,(个人感觉这样的好处是能够让我们没有成本地从其他非数据驱动的 Three.js 项目中,迁移到 Svelte-cubed 中)。

可以看到如果用 纯 Three.js 去写代码,将会比用 Svelte-Cubed 多出好几倍的内容。随着时间的推移,命令式代码也会变得不太容易维护。

image-20211201135223933

通过添加控制器,我们可以轻松进行交互。

打开 src/routes/index.svelte

<SC.Canvas antialias background={new THREE.Color('papayawhip')}>
    <SC.Mesh geometry={new THREE.BoxGeometry()} />
    <SC.PerspectiveCamera position={[1, 1, 3]} />
+    <SC.OrbitControls enableZoom={false} />
</SC.Canvas>

2021-12-01-13.55.11

利用 Svelte 的数据驱动轻松修改 Three.js Objects.

<script>
    import * as THREE from 'three';
    import * as SC from 'svelte-cubed';
+
+    let width = 1;
+    let height = 1;
+    let depth = 1;
</script>

<SC.Canvas antialias background={new THREE.Color('papayawhip')}>
    <SC.Mesh
        geometry={new THREE.BoxGeometry()}
        material={new THREE.MeshStandardMaterial({ color: 0xff3e00 })}
+        scale={[width, height, depth]}
    />
    <SC.PerspectiveCamera position={[1, 1, 3]} />
    <SC.OrbitControls enableZoom={false} />
    <SC.AmbientLight intensity={0.6} />
    <SC.DirectionalLight intensity={0.6} position={[-2, 3, 2]} />
​</SC.Canvas>

+<div class="controls">
+    <label><input type="range" bind:value={width} min={0.1} max={3} step={0.1} /> width</label>
+    <label><input type="range" bind:value={height} min={0.1} max={3} step={0.1} /> height</label>
+    <label><input type="range" bind:value={depth} min={0.1} max={3} step={0.1} /> depth</label>
+</div>
+
+<style>
+    .controls {
+        position: absolute;
+    }
+</style>

2021-12-01-13.59.53

利用数据驱动,动画也可以快速添加。

<script>
    import * as THREE from 'three';
    import * as SC from 'svelte-cubed';

    let width = 1;
    let height = 1;
    let depth = 1;
+
+    let spin = 0;
+
+    SC.onFrame(() => {
+        spin += 0.01;
+    });
</script>

<SC.Canvas antialias background={new THREE.Color('papayawhip')}>
    <SC.Mesh
        geometry={new THREE.BoxGeometry()}
        material={new THREE.MeshStandardMaterial({ color: 0xff3e00 })}
        scale={[width, height, depth]}
+        rotation={[0, spin, 0]}
    />
    <SC.PerspectiveCamera position={[1, 1, 3]} />
    <SC.OrbitControls enableZoom={false} />
    <SC.AmbientLight intensity={0.6} />
    <SC.DirectionalLight intensity={0.6} position={[-2, 3, 2]} />
</SC.Canvas>

2021-12-01 14.01.35

不过随着 Svelte-Cubed 的发布,也有不少的质疑,也有人认为这个东西并没有是真正意义上的"创造新事物",而只是编写了一些胶水层代码。

image-20211201140408397

RH 也亲自进行了回复

image-20211201140446689

简而言之,你使用Svelte Cubed的原因与你使用Svelte(或任何组件框架)本身的原因相同:声明性代码往往比指令性代码更健壮、更易读、更易维护。
直接使用Three绝对没有错,但这相当于直接使用DOM。在某种程度上,很难跟踪没有被表达为层次结构的层次关系,而且管理整个应用程序的状态也成为一种负担。

此外,由于组件有一个可管理的生命周期,如果你使用Vite(或使用Vite的SvelteKit)这样的框架,你可以 "免费 "获得热模块重载这样的东西。一旦你尝试过用这种方式构建场景(例如,在你调整你所放大的物体的属性时保持你的相机位置),Cmd-R驱动的开发就会感觉很苍白了。 ——由 deepl.com 翻译

额外说明:声明式与函数式的区别,创建 div为例:
1.声明式写法<div></div>
2.函数式写法 document.createElement('div');

不过个人感觉,Svelte-Cubed 带来了以下优点

1.声明式带来的层级清晰

2.数据驱动能够带来遍历(写起来比 Three.js 快很多)

3.组件没有非常庞大的情况下,它的体积还非常的小(相比 React、Vue 需要引入一整个运行时就小很多)

既然 Svelte-Cubed 已经融合了 Three.js ,在 meta 概念崛起的年代,离 VR/AR 还会远吗?(事实上只要融合了 Three.js ,使用 Three.js 的生态来写 VR 就已经非常容易了)

最后再列几个在VR/AR 领域比较优秀的框架吧(如果大家对这方面感兴趣),aframe(与 Svelte 异曲同工之妙的声明式),react-three-fiber、babylon.js 。

https://twitter.com/opensas/s...

https://twitter.com/SvelteSoc...

https://svelte-cubed.vercel.a...

https://github.com/Rich-Harri...

https://news.ycombinator.com/...

❤️关注+点赞+收藏+评论+转发❤️ ,原创不易,鼓励笔者创作更好的文章

关注公众号秋风的笔记,一个专注于前端面试、工程化、开源的前端公众号


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK