:warning: This is not even close to production ready. I just started working on this.
Svelte rerendered is a component-library for svelte and sveltekit, which provides a declarative API for building 3D Scenes the svelte way.
There are already a couple svelte libraries which claim to provide such an API. Svelte-gl, sveltethree and svelte-cubed come to mind. Where all of these fall short however is user interaction, transitions and animations. They instead only focus on more or less static 3D scenes.
Building a Scene with svelte-rerendered should feel like writing an SVG. You can use predefined Elements, or import your own Meshes. Rerendered doesn't have explicit materials, instead it offers css-like options for styling Elements. This approach is less flexible than using explicit Materials, but is much easier to work with. It also allows for much easier transitioning of attributes.
<script>
import {Scene, PerspectiveCamera, Box} from 'svelte-rerendered'
</script>
<Scene>
<PerspectiveCamera
position={[-2,-2,2]}
lookingAt={[0,0,0]}
/>
<Box
position={[0,0,1]}
dimensions={[1,0.5,0.5]}
color="#0000ff"/>
<Box
position={[0,0,-1]}
color="normal"
>
</Scene>
For more complex Scenes, you can also extract Elements into other Components. This allows for much more contained and maintainable code.
<!--@component
File: TwoSpheres.svelte
This component contains two sphere primitives.
-->
<script>
import {Sphere} from 'svelte-rerendered'
export let diameter;
$: radius = diameter / 2;
</script>
<Sphere color="#000000" {radius}/>
<Sphere color="#ff0000" radius=3 position={[radius,0,0]}/>
<!--@component
The TwoSpheres component can then simply put into the scene
-->
<script>
import {Scene, PerspectiveCamera} from 'svelte-rerendered'
import TwoSpheres from './TwoSpheres.svelte'
</script>
<Scene>
<PerspectiveCamera/>
<TwoSpheres diameter={6}/>
</Scene>
Placing a svelte-rerendered primitive outside of a Scene is undefined behaviour.
3D Elements have interaction-events, just like regular html elements. Eg:
<Box on:click on:mouseover on:mouseleave etc/>
Rerenders supports two types of animation. Property based, and skeletal animations.
Rerendered's Animation Api is heavily inspired by the Web Animations Api. Most of an objects properties can be animated using transitions. Here is an example on how to make a box spin.
<script lang="ts">
import {Animation, Scene, Box} from 'svelte-rerendered';
//Create an Animation object
const spin = new Animation(
//Keyframes
[
{rotationX: -2 * Math.PI},
{rotationX: 0}
],
//Options
{
duration: 1000,
iterations: Infinity
}
);
onMount(()=>{
spin.play();
})
</script>
<Scene>
<Box color="normal" animations={[spin]}/>
<!--Here I am skipping the Camera setup-->
</Scene>
<!--Animations can be played, paused, resumed and reset-->
<button on:click={()=>spin.pause()}>Pause</button>
<button on:click={()=>spin.resume()}>Resume</button>
You can pass the same instance of an animation to multiple objects. Playing, pausing etc. will affect all animation users. If you want them to be independent, you will have to use multiple instances. Maybe write a factory?
In addition to these animations, you can also pass animations to a Primitives "in" and "out" properties. These will be triggered when the object is mounted/unmounted. The apropriate svelte-lifecycle hooks (on:introstart etc.) are available. :warning: Be careful with iteration count, as the component will not unmount until they have finished!
TODO
Will be added once the API has settled in. Currently everything is subject to change.
This is not remoteley ready to be used in an actual project. If you really want to use this, clone the repository and build the library using
npm run package