<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Warnes</title>
    <description>The latest articles on DEV Community by Alex Warnes (@alexwarnes).</description>
    <link>https://dev.to/alexwarnes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F476342%2F24c9e1c0-42f2-44a0-b8cb-83d7077913d3.jpeg</url>
      <title>DEV Community: Alex Warnes</title>
      <link>https://dev.to/alexwarnes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexwarnes"/>
    <language>en</language>
    <item>
      <title>Svelte-Cubed: Loading Your glTF Models</title>
      <dc:creator>Alex Warnes</dc:creator>
      <pubDate>Thu, 26 May 2022 15:45:13 +0000</pubDate>
      <link>https://dev.to/alexwarnes/svelte-cubed-loading-your-gltf-models-14lf</link>
      <guid>https://dev.to/alexwarnes/svelte-cubed-loading-your-gltf-models-14lf</guid>
      <description>&lt;p&gt;This article is the fourth in a beginner series on creating 3D scenes with svelte-cubed and three.js. If you want to learn how we got here you can start from the beginning:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part One:&lt;/strong&gt; &lt;a href="https://dev.to/alexwarnes/svelte-cubed-an-introduction-to-3d-in-the-browser-1ea3"&gt;Svelte-Cubed: An Introduction to 3D in the Browser&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Part Two:&lt;/strong&gt; &lt;a href="https://dev.to/alexwarnes/svelte-cubed-adding-motion-to-3d-scenes-51lo"&gt;Svelte-Cubed: Adding Motion to 3D Scenes&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Part Three:&lt;/strong&gt; &lt;a href="https://dev.to/alexwarnes/svelte-cubed-creating-an-accessible-and-consistent-experience-across-devices-42ae"&gt;Svelte-Cubed: Creating Accessible and Consistent Experience Across Devices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Octahedrons are great, but in many cases you’ll want to use a more complex model created in a modeling tool like Blender. These models can come in a variety of file types (e.g.   glTF, fbx, etc). We’ll be working with &lt;code&gt;gltf&lt;/code&gt; files, but this approach will work for others as well.&lt;/p&gt;

&lt;p&gt;Simply put, we’re using the plain ol’ threejs &lt;code&gt;GLTFLoader&lt;/code&gt; and then passing the model to a svelte cubed component. Simple. But if you’re new to 3D like me, a step by step walkthrough is a helpful reference and we’ll break it into several small steps to show a model, and then some optional patterns you can implement for reusability and loading.&lt;/p&gt;

&lt;p&gt;If you know what you’re doing and just want to skip to the code, jump into the final scene: &lt;a href="https://svelte.dev/repl/8ea0488302bb434991cc5b82f653cdb5?version=3.48.0" rel="noopener noreferrer"&gt;https://svelte.dev/repl/8ea0488302bb434991cc5b82f653cdb5?version=3.48.0&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What We’ll Cover:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Find cool models&lt;/li&gt;
&lt;li&gt;Create a Svelte component for the model&lt;/li&gt;
&lt;li&gt;Import the GLTFLoader from threejs&lt;/li&gt;
&lt;li&gt;Load the model &lt;code&gt;onMount&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Conditionally pass it into a svelte cubed &lt;code&gt;&amp;lt;Primative /&amp;gt;&lt;/code&gt; component&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Optional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a reusable GLTF Component&lt;/li&gt;
&lt;li&gt;Handle loading states&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1: Find Cool Models
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Threejs Example Models
&lt;/h3&gt;

&lt;p&gt;You can find a bunch of example   glTF/glb models from threejs itself in the &lt;a href="https://github.com/mrdoob/three.js/tree/master/manual/examples/resources/models" rel="noopener noreferrer"&gt;manual&lt;/a&gt; or in the &lt;a href="https://github.com/mrdoob/three.js/tree/master/examples/models/gltf" rel="noopener noreferrer"&gt;examples directory&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Khronos Group
&lt;/h3&gt;

&lt;p&gt;The Khronos group is responsible for the   glTF spec. They also have an &lt;a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0" rel="noopener noreferrer"&gt;examples directory&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  SketchFab
&lt;/h3&gt;

&lt;p&gt;There’s a huge selection of models on &lt;a href="https://sketchfab.com/search?features=downloadable&amp;amp;type=models" rel="noopener noreferrer"&gt;SketchFab&lt;/a&gt;, many of which you can download for free. And of course please give credit to model creators.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Create a Svelte Component for the Model
&lt;/h2&gt;

&lt;p&gt;Use this REPL to start with a basic svelte cubed scene: &lt;a href="https://svelte.dev/repl/c0c34349f1f6405bb25700599a841083?version=3.48.0" rel="noopener noreferrer"&gt;https://svelte.dev/repl/c0c34349f1f6405bb25700599a841083?version=3.48.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add a new component called &lt;code&gt;LittleCity.svelte&lt;/code&gt; with a script tag add two variables:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A URL to the   glTF file&lt;/li&gt;
&lt;li&gt;An empty variable that will hold the model once we get it
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;/*
Model taken from the threejs examples. Created by antonmoek:
https://sketchfab.com/antonmoek
*/&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 3: Import the GLTFLoader from threejs
&lt;/h2&gt;

&lt;p&gt;Whatever filetype you have, threejs probably has a loader for that. In our case (or if using a glb) we’ll use the GLTFLoader. Add that import to the top of your script tag and &lt;strong&gt;BE SURE TO INCLUDE THE FILE EXTENSION.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GLTFLoader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;three/examples/jsm/loaders/GLTFLoader.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Load the Model onMount
&lt;/h2&gt;

&lt;p&gt;When our component mounts, we want to load the model asynchronously and assign it to the &lt;code&gt;model&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;We’ll make a load function first, which will instantiate the loader and return a promise with our model, and then invoke that &lt;code&gt;onMount&lt;/code&gt; and handle the response (which is the model).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// …&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadGLTF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GLTFLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;loadGLTF&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_model&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! We’ll add a catch block later when we make this a reusable component. If you’ve never worked with models before, definitely console log the model to see what that data structure looks like! There are a lot of interesting and (potentially) useful artifacts there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Conditionally Render the Model
&lt;/h2&gt;

&lt;p&gt;Svelte Cubed provides a component called &lt;code&gt;Primitive&lt;/code&gt; to handle almost &lt;em&gt;anything-thats-not-a-mesh&lt;/em&gt; (e.g. models, axes, grid, etc). Primitive can accept props like position, rotation, scale, and other things you would expect.  The Primitive’s &lt;code&gt;object&lt;/code&gt; prop will take the &lt;code&gt;scene&lt;/code&gt; of our model data. Naturally, we only want to render this if we have our model loaded, so we’ll wrap it in a conditional statement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#if model}
  &lt;span class="nt"&gt;&amp;lt;SC.Primitive&lt;/span&gt;
    &lt;span class="na"&gt;object=&lt;/span&gt;&lt;span class="s"&gt;{model.scene}&lt;/span&gt;
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[.05,.05,.05]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Over in &lt;code&gt;App.svelte&lt;/code&gt; let’s import and drop in our component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;// … other imports&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;LittleCity&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./LittleCity.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;SC.Canvas&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- … all the scene stuff is here --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;LittleCity&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/SC.Canvas&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WOW! Take a look around that city!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9xwbw9ye2rcnb6s6uaj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9xwbw9ye2rcnb6s6uaj.png" alt="A low-poly 3D model of a city with several buildings and cars."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s the basic approach for loading an individual model, but that’s a lot of code to rewrite every time you want to load a single model. It might also be nice to indicate the loading status of models. So in the next section we’ll create a basic reusable GLTF component and handle loading.&lt;/p&gt;

&lt;p&gt;To recap, here’s what we have so far in our &lt;code&gt;LittleCity.svelte&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GLTFLoader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;three/examples/jsm/loaders/GLTFLoader.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./stores&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadGLTF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GLTFLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;littleCity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;loadGLTF&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_model&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#if model}
  &lt;span class="nt"&gt;&amp;lt;SC.Primitive&lt;/span&gt;
    &lt;span class="na"&gt;object=&lt;/span&gt;&lt;span class="s"&gt;{model.scene}&lt;/span&gt;
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[.05,.05,.05]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
{/if}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Optional: A Reusable GLTF Component
&lt;/h2&gt;

&lt;p&gt;This is a basic implementation. Share your improvements in the comments!&lt;/p&gt;

&lt;p&gt;First we’ll setup some global state in a new file &lt;code&gt;stores.js&lt;/code&gt; to help us manage model URLs and handle loading states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;readable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;derived&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Contains the status of all models&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;statusOfModels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// { uniqueName: 'LOADING' | 'ERROR' | 'SUCCESS' }&lt;/span&gt;

&lt;span class="c1"&gt;// Returns a boolean if any model has a status of loading&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelsLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusOfModels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statusObj&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusObj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LOADING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Updates a model's status based on its unique name&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateModelStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statusOfModels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// List of example model URLs&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;littleCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mountains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/mountain_landscape/scene.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;llama&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/animals/Llama.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/animals/Pug.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sheep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/animals/Sheep.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cm"&gt;/*
  Models taken from the threejs examples. 
  Little City model created by antonmoek:
  https://sketchfab.com/antonmoek
*/&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we’ll create a new svelte component called &lt;code&gt;ReusableGLTF.svelte&lt;/code&gt; that will accept some props and emit a custom event to share its loading status with its parent component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GLTFLoader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;three/examples/jsm/loaders/GLTFLoader.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createEventDispatcher&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Component Props&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rotation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UniqueName_&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;//   Custom Event to track loading status from parent&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEventDispatcher&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;emitStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;statusChange&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadGLTF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GLTFLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;emitStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LOADING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;loadGLTF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_model&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nf"&gt;emitStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUCCESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error loading model:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nf"&gt;emitStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERROR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#if model}
  &lt;span class="nt"&gt;&amp;lt;SC.Primitive&lt;/span&gt;
      &lt;span class="na"&gt;object=&lt;/span&gt;&lt;span class="s"&gt;{model.scene}&lt;/span&gt;
      &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
      &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
      &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
{/if}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should look pretty similar to our previous &lt;code&gt;LittleCity.svelte&lt;/code&gt; component! Now, I know what you’re thinking, “Math.random() is a red flag!” And you’re right, this implementation would be much stronger with a uuid instead of name to use for tracking loading states. Do it! You can use a uuid package for that and update the loading patterns to use id instead of name. Let’s live dangerously and carry on.&lt;/p&gt;

&lt;p&gt;In our &lt;code&gt;App.svelte&lt;/code&gt; component, let’s import &lt;code&gt;ReusableGLTF.svelte&lt;/code&gt;, import &lt;code&gt;modelURL&lt;/code&gt; and then remove our &lt;code&gt;LittleCity.svelte&lt;/code&gt; component and use our new component instead!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;// … other imports&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReusableGLTF&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ReusableGLTF.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./stores&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;SC.Canvas&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- … all the scene stuff is here --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Don't need this once we have a reusable component! --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;LittleCity /&amp;gt; --&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['littleCity']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"littleCity"&lt;/span&gt; 
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[.05,.05,.05]}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;


&lt;span class="nt"&gt;&amp;lt;/SC.Canvas&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There it is! Let’s add some more…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['llama']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"llama"&lt;/span&gt; 
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[-6,&lt;/span&gt; &lt;span class="err"&gt;17,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt; 
    &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[0,&lt;/span&gt; &lt;span class="na"&gt;Math.PI&lt;/span&gt; &lt;span class="na"&gt;*&lt;/span&gt; &lt;span class="err"&gt;1.25,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['pug']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"pug"&lt;/span&gt; 
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[0,&lt;/span&gt; &lt;span class="err"&gt;17,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['sheep']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"sheep"&lt;/span&gt; 
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[-6,&lt;/span&gt; &lt;span class="err"&gt;17,&lt;/span&gt; &lt;span class="err"&gt;4]}&lt;/span&gt; 
    &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[0,&lt;/span&gt; &lt;span class="na"&gt;Math.PI&lt;/span&gt; &lt;span class="na"&gt;*&lt;/span&gt; &lt;span class="err"&gt;1.25,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The heroes our city needs!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma9fno7m3b9scvsmut6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma9fno7m3b9scvsmut6g.png" alt="A low-poly 3D model of a city with several buildings and cars. There is a llama, sheep, and pug standing on a rooftop overlooking the city."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, let’s handle loading and then we’re done (for now). Remember each &lt;code&gt;ReusableGLTF&lt;/code&gt; component emits a custom event called &lt;code&gt;statusChange&lt;/code&gt;. Learn more about custom events &lt;a href="https://svelte.dev/tutorial/component-events" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Let’s update our &lt;code&gt;App.js&lt;/code&gt; to handle that event by importing from the &lt;code&gt;store.js&lt;/code&gt; and creating a new handle function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;statusOfModels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;modelsLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateModelStatus&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./stores&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleStatusChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;updateModelStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Optional: Handle Loading States
&lt;/h2&gt;

&lt;p&gt;Now add the event listener and handler to each &lt;code&gt;ReusableGLTF&lt;/code&gt; component (or at least any component you want to track loading for) like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['littleCity']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"littleCity"&lt;/span&gt; 
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[.05,.05,.05]}&lt;/span&gt; 
    &lt;span class="na"&gt;on:statusChange=&lt;/span&gt;&lt;span class="s"&gt;{handleStatusChange}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that’s some good data! Feel free to drop in console logs to see what’s going on, or just use &lt;code&gt;$: console.log(“statuses:”, $statusOfModels)&lt;/code&gt; to get a log any time that updates.&lt;/p&gt;

&lt;p&gt;Armed with this data, we can create a new &lt;code&gt;Loading.svelte&lt;/code&gt; component that takes one prop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;showLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#if showLoading}
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"loading-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      Loading...
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;  
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{/if}

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.loading-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#00000088&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fafbfc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt; &lt;span class="m"&gt;.875rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s import it and drop it into our &lt;code&gt;App.svelte&lt;/code&gt; component. We already set up a store that returns a boolean if any model status === loading, so we’ll pass that as a prop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;// … other imports&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Loading.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;Loading&lt;/span&gt; &lt;span class="na"&gt;showLoading=&lt;/span&gt;&lt;span class="s"&gt;{$modelsLoading}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aaaaand we’re done! A lot of what’s going on here can be improved and customized for your needs, but now we have the building blocks of adding and combining glTF/glb models. You could build a whole museum or showcase your own models. We didn’t even talk about animations yet… Maybe next time.&lt;/p&gt;

&lt;p&gt;Share your improvements and implementations in the comments! Seeing what other people build is a huge source of inspiration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;REPL:&lt;/strong&gt;  &lt;a href="https://svelte.dev/repl/8ea0488302bb434991cc5b82f653cdb5?version=3.48.0" rel="noopener noreferrer"&gt;https://svelte.dev/repl/8ea0488302bb434991cc5b82f653cdb5?version=3.48.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App.svelte&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;LittleCity&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./LittleCity.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReusableGLTF&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ReusableGLTF.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Loading.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;statusOfModels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;modelsLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateModelStatus&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./stores&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleStatusChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;updateModelStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;SC.Canvas&lt;/span&gt;
  &lt;span class="na"&gt;background=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;("&lt;/span&gt;&lt;span class="na"&gt;skyblue&lt;/span&gt;&lt;span class="err"&gt;")}&lt;/span&gt;
  &lt;span class="na"&gt;antialias&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;SC.PerspectiveCamera&lt;/span&gt; 
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[-10,&lt;/span&gt; &lt;span class="err"&gt;36,&lt;/span&gt; &lt;span class="err"&gt;20]}&lt;/span&gt;
    &lt;span class="na"&gt;near=&lt;/span&gt;&lt;span class="s"&gt;{0.1}&lt;/span&gt;
    &lt;span class="na"&gt;far=&lt;/span&gt;&lt;span class="s"&gt;{500}&lt;/span&gt;
    &lt;span class="na"&gt;fov=&lt;/span&gt;&lt;span class="s"&gt;{40}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;SC.OrbitControls&lt;/span&gt; 
    &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;{true}&lt;/span&gt;
    &lt;span class="na"&gt;enableZoom=&lt;/span&gt;&lt;span class="s"&gt;{true}&lt;/span&gt;
    &lt;span class="na"&gt;autoRotate=&lt;/span&gt;&lt;span class="s"&gt;{false}&lt;/span&gt;
    &lt;span class="na"&gt;autoRotateSpeed=&lt;/span&gt;&lt;span class="s"&gt;{2}&lt;/span&gt;
    &lt;span class="na"&gt;enableDamping=&lt;/span&gt;&lt;span class="s"&gt;{true}&lt;/span&gt;
    &lt;span class="na"&gt;dampingFactor=&lt;/span&gt;&lt;span class="s"&gt;{0.1}&lt;/span&gt;
    &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;{[-6,&lt;/span&gt; &lt;span class="err"&gt;17,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;SC.DirectionalLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;(0&lt;/span&gt;&lt;span class="na"&gt;xffffff&lt;/span&gt;&lt;span class="err"&gt;)}&lt;/span&gt;
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[0,10,10]}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{0.75}&lt;/span&gt;
    &lt;span class="na"&gt;shadow=&lt;/span&gt;&lt;span class="s"&gt;{false}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SC.AmbientLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;(0&lt;/span&gt;&lt;span class="na"&gt;xffffff&lt;/span&gt;&lt;span class="err"&gt;)}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{0.75}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- Don't need this once we have a reusable component! --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!--   &amp;lt;LittleCity /&amp;gt; --&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['littleCity']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"littleCity"&lt;/span&gt; 
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[.05,.05,.05]}&lt;/span&gt; 
    &lt;span class="na"&gt;on:statusChange=&lt;/span&gt;&lt;span class="s"&gt;{handleStatusChange}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['llama']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"llama"&lt;/span&gt; 
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[-6,&lt;/span&gt; &lt;span class="err"&gt;17,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt; 
    &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[0,&lt;/span&gt; &lt;span class="na"&gt;Math.PI&lt;/span&gt; &lt;span class="na"&gt;*&lt;/span&gt; &lt;span class="err"&gt;1.25,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt; 
    &lt;span class="na"&gt;on:statusChange=&lt;/span&gt;&lt;span class="s"&gt;{handleStatusChange}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['pug']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"pug"&lt;/span&gt; 
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[0,&lt;/span&gt; &lt;span class="err"&gt;17,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt; 
    &lt;span class="na"&gt;on:statusChange=&lt;/span&gt;&lt;span class="s"&gt;{handleStatusChange}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ReusableGLTF&lt;/span&gt; 
    &lt;span class="na"&gt;modelURL=&lt;/span&gt;&lt;span class="s"&gt;{modelURL['sheep']}&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"sheep"&lt;/span&gt; 
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[-6,&lt;/span&gt; &lt;span class="err"&gt;17,&lt;/span&gt; &lt;span class="err"&gt;4]}&lt;/span&gt; 
    &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[0,&lt;/span&gt; &lt;span class="na"&gt;Math.PI&lt;/span&gt; &lt;span class="na"&gt;*&lt;/span&gt; &lt;span class="err"&gt;1.25,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt; 
    &lt;span class="na"&gt;on:statusChange=&lt;/span&gt;&lt;span class="s"&gt;{handleStatusChange}&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/SC.Canvas&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Loading&lt;/span&gt; &lt;span class="na"&gt;showLoading=&lt;/span&gt;&lt;span class="s"&gt;{$modelsLoading}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ReusableGLTF.svelte&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GLTFLoader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;three/examples/jsm/loaders/GLTFLoader.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createEventDispatcher&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Component Props&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rotation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UniqueName_&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;//   Custom Event to track loading status from parent&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEventDispatcher&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;emitStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;statusChange&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadGLTF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GLTFLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modelURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;emitStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LOADING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;loadGLTF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_model&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nf"&gt;emitStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUCCESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error loading model:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nf"&gt;emitStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERROR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#if model}
  &lt;span class="nt"&gt;&amp;lt;SC.Primitive&lt;/span&gt;
      &lt;span class="na"&gt;object=&lt;/span&gt;&lt;span class="s"&gt;{model.scene}&lt;/span&gt;
      &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
      &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
      &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
{/if}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Loading.svelte&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;showLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#if showLoading}
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"loading-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      Loading...
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;  
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{/if}

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.loading-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#00000088&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fafbfc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt; &lt;span class="m"&gt;.875rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;stores.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;readable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;derived&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Contains the status of all models&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;statusOfModels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// { uniqueName: 'LOADING' | 'ERROR' | 'SUCCESS' }&lt;/span&gt;

&lt;span class="c1"&gt;// Returns a boolean if any model has a status of loading&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelsLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusOfModels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statusObj&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusObj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LOADING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Updates a model's status based on its unique name&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateModelStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statusOfModels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// List of example model URLs&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;littleCity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mountains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/mountain_landscape/scene.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;llama&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/animals/Llama.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/animals/Pug.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sheep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://threejs.org/manual/examples/resources/models/animals/Sheep.gltf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>svelte</category>
      <category>threejs</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Svelte-Cubed: Creating an Accessible and Consistent Experience Across Devices</title>
      <dc:creator>Alex Warnes</dc:creator>
      <pubDate>Tue, 10 May 2022 17:13:25 +0000</pubDate>
      <link>https://dev.to/alexwarnes/svelte-cubed-creating-an-accessible-and-consistent-experience-across-devices-42ae</link>
      <guid>https://dev.to/alexwarnes/svelte-cubed-creating-an-accessible-and-consistent-experience-across-devices-42ae</guid>
      <description>&lt;p&gt;This article is the third in a beginner series on creating 3D scenes with svelte-cubed and three.js. If you want to learn how we got here you can start from the beginning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Part One: &lt;a href="https://dev.to/alexwarnes/svelte-cubed-an-introduction-to-3d-in-the-browser-1ea3"&gt;Svelte-Cubed: An Introduction to 3D in the Browser&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part Two: &lt;a href="https://dev.to/alexwarnes/svelte-cubed-adding-motion-to-3d-scenes-51lo"&gt;Svelte-Cubed: Adding Motion to 3D Scenes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this short article, we’re going to look at two sort-of unrelated topics. However, both fall under the umbrella of improving user experience:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using &lt;code&gt;prefers-reduced-motion&lt;/code&gt; to conditionally animate/transition things in our scene&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using threejs clock and &lt;code&gt;getDelta()&lt;/code&gt; to render the same motion for users with different device frame rates&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the REPL where part two left off to get you started:&lt;br&gt;
&lt;a href="https://svelte.dev/repl/9b3b351fe187421b84a6f1616e2c9e3d" rel="noopener noreferrer"&gt;https://svelte.dev/repl/9b3b351fe187421b84a6f1616e2c9e3d&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Conditional Motion: prefers-reduced-motion
&lt;/h2&gt;

&lt;p&gt;Why does it matter?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Not everyone likes decorative animations or transitions, and some users outright experience motion sickness when faced with parallax scrolling, zooming effects, and so on. The user preference media query prefers-reduced-motion lets you design a motion-reduced variant of your site for users who have expressed this preference.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;- Thomas Steiner (&lt;a href="https://twitter.com/tomayac" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;) in &lt;a href="https://web.dev/prefers-reduced-motion/" rel="noopener noreferrer"&gt;prefers-reduced-motion: Sometimes less movement is more&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we want our scenes to be enjoyable for everyone, so first let’s figure out how to detect this preference in JavaScript so we can use it in our Svelte component. I’ll be using an approach from Geoff Rich (&lt;a href="https://twitter.com/geoffrich_" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;) explained in his post &lt;a href="https://geoffrich.net/posts/svelte-prefers-reduced-motion-store/" rel="noopener noreferrer"&gt;A Svelte store for prefers-reduced-motion&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In a new javascript file we’ll call &lt;code&gt;stores.js&lt;/code&gt; we can steal all of Geoff’s code (and cite it for future reference!) and paste it in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/*
    Source: Geoff Rich, 
    "A Svelte store for prefers-reduced-motion", 
    URL: https://geoffrich.net/posts/svelte-prefers-reduced-motion-store/
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(prefers-reduced-motion: reduce)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getInitialMotionPreference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getInitialMotionPreference&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateMotionPreference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateMotionPreference&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateMotionPreference&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;reducedMotion&lt;/code&gt; store provides a boolean that we can subscribe and react to anywhere in our application if the value changes. How can we use it? Well, anywhere we animate we can first check the preference and adjust as needed. Our motion is coming from two sources: the tweened store and our &lt;code&gt;SC.onFrame()&lt;/code&gt; callback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;: if a user prefers reduced motion, our tweened store duration will be 0 (i.e. it will go from value a to value b instantly).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./stores&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tweened&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$reducedMotion&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;easing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;elasticOut&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it? That’s it!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt;: if a user &lt;em&gt;does not&lt;/em&gt; prefer reduced motion, we can update the rotation on every frame.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;$reducedMotion&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nx"&gt;SC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;rotate&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can you test it? Geoff has us covered: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Here's how to simulate the setting in &lt;a href="https://developers.google.com/web/updates/2019/10/devtools#userpreferences" rel="noopener noreferrer"&gt;Chrome&lt;/a&gt; DevTools and where to enable the setting in various &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion#user_preferences" rel="noopener noreferrer"&gt;OSes and Firefox&lt;/a&gt;&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since you’re only simulating the setting in devtools, you’ll need to keep devtools open and refresh the REPL to see how things change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh47k89gvr051xkhu1ehc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh47k89gvr051xkhu1ehc.gif" alt="GIF showing animated and non-animated transitions when simulating the prefers-reduced-motion browser setting in Chrome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Variable Frame Rates Across Devices
&lt;/h2&gt;

&lt;p&gt;What do all those words mean? Much smarter people can explain it better than me, but I’ll take a shot and then point you to a better explanation. &lt;/p&gt;

&lt;p&gt;Some computer/monitor setups have powerful graphics and some do not. &lt;em&gt;For example&lt;/em&gt;, our Octahedron is rotating 0.1 radians on each frame. So a setup running at 60 frames per second (fps) is watching your Octahedron rotate 0.1 radians 60 times every second. A less powerful setup running at 30fps is watching your Octahedron rotate 0.1 radians only 30 times every second. Those are very different experiences!&lt;/p&gt;

&lt;p&gt;For a more accurate and in-depth explanation checkout &lt;a href="https://discoverthreejs.com/book/first-steps/animation-loop/#fixed-and-dynamic-frames" rel="noopener noreferrer"&gt;The Animation Loop&lt;/a&gt; chapter from the open source book &lt;em&gt;Discover three.js&lt;/em&gt; by Lewy Blue (&lt;a href="https://twitter.com/lewy_blue" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;). If you are new to three.js I highly recommend taking some time to go through the whole book!&lt;/p&gt;

&lt;p&gt;Basically we need a way to standardize our hardcoded value inside &lt;code&gt;SC.onFrame&lt;/code&gt; based on the current frame rate. We can do just that using the threejs Clock and the method &lt;code&gt;getDelta()&lt;/code&gt; and multiplying our value by delta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Clock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;SC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;rotate&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDelta&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow, that’s slow. But it’s slow for &lt;em&gt;everyone&lt;/em&gt;! Now we can adjust our rotation value to get the rate we want (try 0.5).&lt;/p&gt;

&lt;p&gt;In the next article we’ll shift away from our Octahedron friend and dive into loading one or more glTF models into the scene!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;REPL: &lt;a href="https://svelte.dev/repl/c301f0ac026d45bdbf4facf55b921d1f?version=3.48.0" rel="noopener noreferrer"&gt;https://svelte.dev/repl/c301f0ac026d45bdbf4facf55b921d1f?version=3.48.0&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Octo.svelte
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tweened&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte/motion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;elasticOut&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte/easing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./stores&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tweened&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$reducedMotion&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;easing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;elasticOut&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// reactive statement to update scale based on scaleType&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SMALL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LARGE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.75&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rotate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;$reducedMotion&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Clock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;SC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;rotate&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDelta&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;SC.Canvas&lt;/span&gt; &lt;span class="na"&gt;background=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;seagreen&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;SC.AmbientLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{.5}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;SC.DirectionalLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{.75}&lt;/span&gt;
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[10,&lt;/span&gt; &lt;span class="err"&gt;10,&lt;/span&gt; &lt;span class="err"&gt;10]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- MESHES --&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;SC.Mesh&lt;/span&gt;
    &lt;span class="na"&gt;geometry=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.OctahedronGeometry&lt;/span&gt;&lt;span class="err"&gt;()}&lt;/span&gt;
    &lt;span class="na"&gt;material=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.MeshStandardMaterial&lt;/span&gt;&lt;span class="err"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;color:&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;salmon&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;
    &lt;span class="err"&gt;})}&lt;/span&gt;
        &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[rotate,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[$scale,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- CAMERA --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SC.PerspectiveCamera&lt;/span&gt; &lt;span class="na"&gt;near=&lt;/span&gt;&lt;span class="s"&gt;{1}&lt;/span&gt; &lt;span class="na"&gt;far=&lt;/span&gt;&lt;span class="s"&gt;{100}&lt;/span&gt; &lt;span class="na"&gt;fov=&lt;/span&gt;&lt;span class="s"&gt;{55}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/SC.PerspectiveCamera&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;SC.OrbitControls&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/SC.Canvas&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"controls"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    SMALL
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"SMALL"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    MEDIUM
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"MEDIUM"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    LARGE
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"LARGE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.controls&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#00000088&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  stores.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="cm"&gt;/*
    Source: Geoff Rich, 
    "A Svelte store for prefers-reduced-motion", 
    URL: https://geoffrich.net/posts/svelte-prefers-reduced-motion-store/
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(prefers-reduced-motion: reduce)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getInitialMotionPreference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getInitialMotionPreference&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateMotionPreference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateMotionPreference&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateMotionPreference&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>svelte</category>
      <category>threejs</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Svelte-Cubed: Adding Motion to 3D Scenes</title>
      <dc:creator>Alex Warnes</dc:creator>
      <pubDate>Mon, 31 Jan 2022 22:29:40 +0000</pubDate>
      <link>https://dev.to/alexwarnes/svelte-cubed-adding-motion-to-3d-scenes-51lo</link>
      <guid>https://dev.to/alexwarnes/svelte-cubed-adding-motion-to-3d-scenes-51lo</guid>
      <description>&lt;p&gt;This article is the second in a beginner series on creating 3D scenes with svelte-cubed and three.js. We’re picking up where we left off, so if you want to learn how we got here you can start from the beginning:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part One: &lt;a href="https://dev.to/alexwarnes/svelte-cubed-an-introduction-to-3d-in-the-browser-1ea3"&gt;Svelte-Cubed: An Introduction to 3D in the Browser&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article we will cover two different approaches to moving things around in your scene with &lt;strong&gt;constant motion&lt;/strong&gt; using &lt;code&gt;onFrame&lt;/code&gt; and &lt;strong&gt;on-demand motion&lt;/strong&gt; using svelte’s tweened stores and easing functions.&lt;/p&gt;

&lt;p&gt;Here’s the REPL where part one left off to get you started:&lt;br&gt;
&lt;a href="https://svelte.dev/repl/71b063fc410543598e8a727999cf7bbe" rel="noopener noreferrer"&gt;https://svelte.dev/repl/71b063fc410543598e8a727999cf7bbe&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s get moving!&lt;/p&gt;
&lt;h2&gt;
  
  
  Constant Motion
&lt;/h2&gt;

&lt;p&gt;That octahedron is cool, but it’s the kind of shape that would be cooler if it were spinning all the time. What we want to do is adjust the rotation a &lt;strong&gt;little bit&lt;/strong&gt;, multiple times &lt;strong&gt;per second&lt;/strong&gt;. First thought might be to use JavaScript’s &lt;code&gt;setInterval&lt;/code&gt; and make an update every x number of milliseconds. But there’s a more performant way! &lt;/p&gt;

&lt;p&gt;Svelte-cubed gives us a method called &lt;code&gt;onFrame(callback)&lt;/code&gt; that accepts a callback method where we can make some change to our scene on each frame. Let’s give it a try.&lt;/p&gt;

&lt;p&gt;A mesh has a &lt;code&gt;rotation&lt;/code&gt; property that accepts an array with x, y, z radian values that each describe the mesh’s rotation along the respective axis (you can brush up on your radians here: &lt;a href="https://www.khanacademy.org/math/algebra2/x2ec2f6f830c9fb89:trig/x2ec2f6f830c9fb89:radians/v/introduction-to-radians" rel="noopener noreferrer"&gt;Khan Academy: Intro to Radians&lt;/a&gt;). We want to rotate our mesh along the y-axis, so we’ll declare a &lt;code&gt;rotate&lt;/code&gt; variable, update it inside the &lt;code&gt;onFrame&lt;/code&gt; callback, and then pass it into our mesh in the &lt;code&gt;Octo.svelte&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// … &lt;/span&gt;

&lt;span class="c1"&gt;// Declare our variable&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rotate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;SC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Every frame, assign these radians to rotationY&lt;/span&gt;
  &lt;span class="nx"&gt;rotationY&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- add the rotation property to the mesh and use our new variable --&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;SC.Mesh&lt;/span&gt;
    &lt;span class="na"&gt;geometry=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.OctahedronGeometry&lt;/span&gt;&lt;span class="err"&gt;()}&lt;/span&gt;
    &lt;span class="na"&gt;material=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.MeshStandardMaterial&lt;/span&gt;&lt;span class="err"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;color:&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;salmon&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;
    &lt;span class="err"&gt;})}&lt;/span&gt;
    &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[0,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;0]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fko6ri4d5ncl1sslf35vz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fko6ri4d5ncl1sslf35vz.gif" alt="A salmon color octahedron rotating on its y-axis"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s moving! I just drank a red bull, so let’s go big and use the rotation variable for ALL THREE mesh axes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;SC.Mesh&lt;/span&gt;
    &lt;span class="na"&gt;geometry=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.OctahedronGeometry&lt;/span&gt;&lt;span class="err"&gt;()}&lt;/span&gt;
    &lt;span class="na"&gt;material=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.MeshStandardMaterial&lt;/span&gt;&lt;span class="err"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;color:&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;salmon&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;
    &lt;span class="err"&gt;})}&lt;/span&gt;
    &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[rotate,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6x37mn5zk7aqqfyjnxs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6x37mn5zk7aqqfyjnxs.gif" alt="A salmon color octahedron rotating on every axis simultaneously"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If that’s too &lt;em&gt;spintense&lt;/em&gt; for your taste, adjust as you will. Experiment with the amount of rotation we used in the &lt;code&gt;onFrame&lt;/code&gt; callback (but don’t forget we’re using radians!).&lt;/p&gt;

&lt;p&gt;This motion makes our mesh a lot more visually engaging, and you can see how it would be helpful for something like a planet. Remember we can use this approach for updating &lt;em&gt;any&lt;/em&gt; value: rotation, position, or scale.&lt;/p&gt;

&lt;p&gt;But what if we have some kind of motion that we only want to happen once? Say for example we want to toggle our octahedron size between small, medium, and large. It would be cumbersome (and perform poorly) to add a bunch of conditional logic inside the &lt;code&gt;onFrame&lt;/code&gt; call back. Svelte gives us the perfect tool for the job with a &lt;em&gt;tweened store&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transitional Motion: On-Demand
&lt;/h2&gt;

&lt;p&gt;Let’s break down what we want:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A set of radio inputs: small, medium, large (medium by default)&lt;/li&gt;
&lt;li&gt;When I select a radio input, the octahedron should &lt;em&gt;scale&lt;/em&gt; to match the selected size&lt;/li&gt;
&lt;li&gt;The scaling should transition smoothly from one size to another&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  STEP 1: Svelte Radio Input Binding (bonus Lesson)
&lt;/h3&gt;

&lt;p&gt;We’ll create a variable to hold the selection called &lt;code&gt;scaleType&lt;/code&gt; and set the initial value to “MEDIUM”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;MEDIUM&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nailed it. Now below our canvas markup, we’ll create three radio inputs with labels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"controls"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    SMALL
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"SMALL"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    MEDIUM
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"MEDIUM"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    LARGE
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"LARGE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that each input has a value and we &lt;code&gt;bind&lt;/code&gt; all of them to the &lt;code&gt;scaleType&lt;/code&gt; variable. This is some classic Svelte simplicity, no event handling to worry about. If you want to learn more about group bindings for radio and checkbox inputs, check out &lt;a href="https://svelte.dev/tutorial/group-inputs" rel="noopener noreferrer"&gt;the official tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But we still can’t see anything, so add a style block under all the markup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.controls&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#00000088&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje35wsv7602kbpdesyl2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje35wsv7602kbpdesyl2.png" alt="A salmon octahedron in front of a seagreen background with a form in the upper left corner containing small, medium, large radio buttons."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  STEP 2: Reactive Scaling
&lt;/h3&gt;

&lt;p&gt;Our &lt;code&gt;scaleType&lt;/code&gt; variable updates whenever the selection changes, and any time &lt;code&gt;scaleType&lt;/code&gt; changes we want to update the mesh’s scale properties. Back up in our script, let’s use another wonderful Svelte feature called a reactive statement &lt;a href="https://dev.tomore%20info%20here"&gt;https://svelte.dev/tutorial/reactive-statements&lt;/a&gt; to do just that. &lt;/p&gt;

&lt;p&gt;Below we'll declare a variable called &lt;code&gt;scale&lt;/code&gt; with an initial value of 1, setup a reactive statement to update &lt;code&gt;scale&lt;/code&gt; based on &lt;code&gt;scaleType&lt;/code&gt;, and then add the scale array to our mesh and use our scale value for the x, y, and z scaling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// … other stuff in our script&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// reactive statement&lt;/span&gt;
&lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SMALL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LARGE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.75&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- … other stuff in our markup --&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;SC.Mesh&lt;/span&gt;
    &lt;span class="na"&gt;geometry=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.OctahedronGeometry&lt;/span&gt;&lt;span class="err"&gt;()}&lt;/span&gt;
    &lt;span class="na"&gt;material=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.MeshStandardMaterial&lt;/span&gt;&lt;span class="err"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;color:&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;salmon&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;
    &lt;span class="err"&gt;})}&lt;/span&gt;
    &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[rotate,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[scale,&lt;/span&gt; &lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I know, that was a lot. Just to review: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the inputs control the &lt;code&gt;scaleType&lt;/code&gt; small/medium/large&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;scale&lt;/code&gt; variable reacts to any change to the &lt;code&gt;scaleType&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;we pass the &lt;code&gt;scale&lt;/code&gt; value into our mesh’s scale array&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tc3sfnini0kluvo685m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tc3sfnini0kluvo685m.gif" alt="A salmon color octahedron that immediately changes size when small, medium, or large is selected."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  STEP 3: Smooth Transitions
&lt;/h3&gt;

&lt;p&gt;Right now our mesh jumps directly from one scale to another, and what we’d like to see is a smooth transition. When we go from small (.5) to large (1.75) we’d like that to take about 2 seconds and progress through a handful of values in &lt;em&gt;between&lt;/em&gt; the current scale and the next scale. Svelte provides something called a &lt;em&gt;tweened store&lt;/em&gt; for just this type of thing! &lt;a href="https://dev.tomore%20info%20here"&gt;https://svelte.dev/tutorial/tweened&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A tweened store is like a fancy variable that we can give a value, say 1. When we update that value to, say 1.75, the store value will shift to that value over time based on how we configure it. Let’s see what that looks like by updating our &lt;code&gt;scale&lt;/code&gt; to be a tweened store and seeing what breaks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tweened&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;motion&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tweened&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything is broken! That’s because tweened stores are fancy variables (they’re actually just objects) and we need to access them in a special way &lt;a href="https://svelte.dev/tutorial/writable-stores" rel="noopener noreferrer"&gt;more info here&lt;/a&gt;. The shorthand way for reading and writing the value of a svelte store is with the &lt;code&gt;$&lt;/code&gt; prefix. So everywhere we read or write to &lt;code&gt;scale&lt;/code&gt; needs to be updated to &lt;code&gt;$scale&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Inside our reactive statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// reactive statement&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SMALL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LARGE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.75&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And inside our mesh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;SC.Mesh&lt;/span&gt;
    &lt;span class="na"&gt;geometry=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.OctahedronGeometry&lt;/span&gt;&lt;span class="err"&gt;()}&lt;/span&gt;
    &lt;span class="na"&gt;material=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.MeshStandardMaterial&lt;/span&gt;&lt;span class="err"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;color:&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;salmon&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;
    &lt;span class="err"&gt;})}&lt;/span&gt;
    &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[rotate,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[$scale,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now look at that transition!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsdrgllordegfsqpz38r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsdrgllordegfsqpz38r.gif" alt="A salmon color octahedron that smoothly transitions to its new size when small, medium, or large is selected."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing Transitions
&lt;/h3&gt;

&lt;p&gt;That’s a smooth transition, but you know what would make it even better? Changing the duration and the easing. Well that’s just the second argument to a tweened store! And of course Svelte provides &lt;a href="https://svelte.dev/examples/easing" rel="noopener noreferrer"&gt;a ton of great easing functions&lt;/a&gt; out of the box. I’ll use one here, but you should definitely play around with different options!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;elasticOut&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;easing&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tweened&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;easing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;elasticOut&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgl128vfa92ovsse3t2y5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgl128vfa92ovsse3t2y5.gif" alt="A salmon color octahedron that has a bouncy elastic transition to its new size when small, medium, or large is selected."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next article we’ll cover animation accessibility concerns and how to use &lt;code&gt;prefers-reduced-motion&lt;/code&gt; to avoid using animations for users who don’t want them, and how to accommodate screens with varying frame-rates so your animations can look consistent across devices.&lt;/p&gt;

&lt;p&gt;Nice work!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxcf26r0ij3hbnw2992l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxcf26r0ij3hbnw2992l.gif" alt="A robot giving you a thumbs up."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;REPL:&lt;/strong&gt; &lt;a href="https://svelte.dev/repl/9b3b351fe187421b84a6f1616e2c9e3d" rel="noopener noreferrer"&gt;https://svelte.dev/repl/9b3b351fe187421b84a6f1616e2c9e3d&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  App.svelte
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Octo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Octo.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;What is an Octahedron?&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"scene-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Octo&amp;gt;&amp;lt;/Octo&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;An octahedron is a three-dimensional shape having eight plane faces, especially a regular solid figure with eight equal triangular faces.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.scene-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* position relative let's the canvas position itself relative to this container */&lt;/span&gt;
        &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;75%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Octo.svelte
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tweened&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte/motion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;elasticOut&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte/easing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tweened&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;easing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;elasticOut&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// reactive statement to update scale based on scaleType&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SMALL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LARGE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.75&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rotate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;SC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;rotate&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;SC.Canvas&lt;/span&gt; &lt;span class="na"&gt;background=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;seagreen&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;SC.AmbientLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{.5}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;SC.DirectionalLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{.75}&lt;/span&gt;
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[10,&lt;/span&gt; &lt;span class="err"&gt;10,&lt;/span&gt; &lt;span class="err"&gt;10]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- MESHES --&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;SC.Mesh&lt;/span&gt;
    &lt;span class="na"&gt;geometry=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.OctahedronGeometry&lt;/span&gt;&lt;span class="err"&gt;()}&lt;/span&gt;
    &lt;span class="na"&gt;material=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.MeshStandardMaterial&lt;/span&gt;&lt;span class="err"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;color:&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;salmon&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;
    &lt;span class="err"&gt;})}&lt;/span&gt;
        &lt;span class="na"&gt;rotation=&lt;/span&gt;&lt;span class="s"&gt;{[rotate,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rotate&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
    &lt;span class="na"&gt;scale=&lt;/span&gt;&lt;span class="s"&gt;{[$scale,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="err"&gt;]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- CAMERA --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SC.PerspectiveCamera&lt;/span&gt; &lt;span class="na"&gt;near=&lt;/span&gt;&lt;span class="s"&gt;{1}&lt;/span&gt; &lt;span class="na"&gt;far=&lt;/span&gt;&lt;span class="s"&gt;{100}&lt;/span&gt; &lt;span class="na"&gt;fov=&lt;/span&gt;&lt;span class="s"&gt;{55}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/SC.PerspectiveCamera&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;SC.OrbitControls&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- all of our scene stuff will go here! --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/SC.Canvas&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"controls"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    SMALL
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"SMALL"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    MEDIUM
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"MEDIUM"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    LARGE
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;bind:group=&lt;/span&gt;&lt;span class="s"&gt;{scaleType}&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"LARGE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.controls&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#00000088&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Edits
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;24 May 2022:&lt;/strong&gt; Updated &lt;em&gt;octohedron&lt;/em&gt; to be spelled correctly &lt;em&gt;octahedron&lt;/em&gt; (smh)&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>threejs</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Svelte-Cubed: An Introduction to 3D in the Browser</title>
      <dc:creator>Alex Warnes</dc:creator>
      <pubDate>Thu, 27 Jan 2022 02:18:13 +0000</pubDate>
      <link>https://dev.to/alexwarnes/svelte-cubed-an-introduction-to-3d-in-the-browser-1ea3</link>
      <guid>https://dev.to/alexwarnes/svelte-cubed-an-introduction-to-3d-in-the-browser-1ea3</guid>
      <description>&lt;p&gt;Whatever you're making from data visualizations, or telling stories, being creative, selling products, 3D scenes open up new ways for people to engage with your content. (and it's also just really fun)&lt;/p&gt;

&lt;p&gt;This article will walk through the basics of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setting up a scene&lt;/li&gt;
&lt;li&gt;Adding lights and shapes&lt;/li&gt;
&lt;li&gt;Incorporating the scene into a site&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;We'll be using &lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;svelte&lt;/a&gt;, &lt;a href="https://threejs.org/" rel="noopener noreferrer"&gt;three.js&lt;/a&gt;, and &lt;a href="https://svelte-cubed.vercel.app/" rel="noopener noreferrer"&gt;svelte-cubed&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you're unfamiliar with these tools and just want to make something that looks cool you can still follow along! And if you want to learn more, that's great too. Here are some helpful introductory resources you can come back to later (or banish into eternal browser-tab land):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://svelte.dev/tutorial/basics" rel="noopener noreferrer"&gt;Interactive official Svelte tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtube.com/playlist?list=PL4cUxeGkcC9hlbrVO_2QFVqVPhlZmz7tO" rel="noopener noreferrer"&gt;Svelte for Beginners on YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discoverthreejs.com/book/introduction/" rel="noopener noreferrer"&gt;Interactive three.js tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best way to learn is to build, so let's go.&lt;/p&gt;

&lt;p&gt;(full code is at the bottom if you run into any issues)&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a Scene: Canvas and Camera
&lt;/h2&gt;

&lt;p&gt;Head on over to the Svelte REPL: &lt;a href="https://svelte.dev/repl/" rel="noopener noreferrer"&gt;https://svelte.dev/repl/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where we'll do all our development so you can easily share your scene and won't have to worry about setting anything up on your machine.&lt;/p&gt;

&lt;p&gt;Start by importing our main tools in the script tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// all of our javascript and logic would go here&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables us to use THREE and SC inside our App.svelte file. (And don't worry about bundle size; the Svelte compiler will optimize that for us)&lt;/p&gt;

&lt;p&gt;Every 3D scene is projected onto a canvas, so let's create one. Under the script tags, add a svelte-cubed canvas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;SC.Canvas&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- all of our scene stuff will go here! --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/SC.Canvas&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Way to go! Now buy my book... just kidding. Let's continue.&lt;/p&gt;

&lt;p&gt;We can't see anything because we have no camera. We'll go with the classic &lt;strong&gt;perspective&lt;/strong&gt; camera (you can experiment with the &lt;strong&gt;orthographic&lt;/strong&gt; camera at the end to see how it differs).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="c"&gt;&amp;lt;!-- CAMERA --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;SC.PerspectiveCamera&lt;/span&gt; &lt;span class="na"&gt;near=&lt;/span&gt;&lt;span class="s"&gt;{1}&lt;/span&gt; &lt;span class="na"&gt;far=&lt;/span&gt;&lt;span class="s"&gt;{100}&lt;/span&gt; &lt;span class="na"&gt;fov=&lt;/span&gt;&lt;span class="s"&gt;{55}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;wait wut? Okay, so we have to configure our camera a little bit to create our &lt;em&gt;view frustum&lt;/em&gt; aka what our camera can see. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;near:&lt;/strong&gt; anything closer than this will not be shown by the camera (unit: meters)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;far:&lt;/strong&gt; anything farther than this will not be shown by the camera (unit: meters)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fov:&lt;/strong&gt; (Field of View) anything outside of this angle will not be shown by the camera (unit: degrees)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see if it's working by creating a new color and setting it as our canvas background:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;SC.Canvas&lt;/span&gt; &lt;span class="na"&gt;background=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;seagreen&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- CAMERA --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SC.PerspectiveCamera&lt;/span&gt; &lt;span class="na"&gt;near=&lt;/span&gt;&lt;span class="s"&gt;{1}&lt;/span&gt; &lt;span class="na"&gt;far=&lt;/span&gt;&lt;span class="s"&gt;{100}&lt;/span&gt; &lt;span class="na"&gt;fov=&lt;/span&gt;&lt;span class="s"&gt;{55}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- all of our scene stuff will go here! --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/SC.Canvas&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3m28xda92v18t6fc27j3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3m28xda92v18t6fc27j3.png" alt="A seagreen html canvas without any objects on it."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Shapes
&lt;/h2&gt;

&lt;p&gt;What regular people call shapes are called a "mesh" in 3D-land, so we'll use that word from now on. A mesh is a combination of a geometry and a material, just like your table: it has a geometry (e.g. rectangle or oval) and a material (e.g. wood or glass). &lt;/p&gt;

&lt;p&gt;Three.js offers many &lt;a href="https://threejs.org/docs/index.html?q=geometry" rel="noopener noreferrer"&gt;geometries&lt;/a&gt; and &lt;a href="https://threejs.org/docs/index.html?q=material" rel="noopener noreferrer"&gt;materials&lt;/a&gt; you can experiment with, and each variant can take several unique properties. For now let's add an octahedron... and together we'll learn what an octahedron is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="c"&gt;&amp;lt;!-- MESHES --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;SC.Mesh&lt;/span&gt;
  &lt;span class="na"&gt;geometry=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.OctahedronGeometry&lt;/span&gt;&lt;span class="err"&gt;()}&lt;/span&gt;
  &lt;span class="na"&gt;material=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.MeshStandardMaterial&lt;/span&gt;&lt;span class="err"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;color:&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;salmon&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;
  &lt;span class="err"&gt;})}&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we passed a javascript object into our new material with a &lt;em&gt;color&lt;/em&gt; property. This is where you can handle all sorts of material enhancements, but we'll just use color for now.&lt;/p&gt;

&lt;p&gt;And there it is! But it's not the color of salmon :( That's happening because our &lt;em&gt;MeshStandardMaterial&lt;/em&gt; interacts with light and we don't have any lights! (You can experiment with a MeshBasicMaterial for something that does not interact with light to compare)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi89nhe91aw16cgv710he.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi89nhe91aw16cgv710he.png" alt="A seagreen html canvas without an octahedron that is entirely black because there is no light."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Light
&lt;/h2&gt;

&lt;p&gt;Unsurprisingly three.js offers many lighting options. Not sure how to incorporate this pun but: something, something, &lt;em&gt;the unbearable lightness of three-ing&lt;/em&gt;. Now we're going to add two lights: a &lt;strong&gt;directional&lt;/strong&gt; light and an &lt;strong&gt;ambient&lt;/strong&gt; light, and you'll probably get the gist of what they do in the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;SC.DirectionalLight&lt;/span&gt;
  &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;
  &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{.75}&lt;/span&gt;
  &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[10,&lt;/span&gt; &lt;span class="err"&gt;10,&lt;/span&gt; &lt;span class="err"&gt;10]}&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frf532kmojwie1mc7gvu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frf532kmojwie1mc7gvu1.png" alt="A seagreen html canvas with a dimly lit salmon-color octahedron."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how the un-lit sides are really dark. Let's add the ambient light:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
  &lt;span class="nt"&gt;&amp;lt;SC.AmbientLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{.5}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2titm9s9frizntzi2wp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2titm9s9frizntzi2wp.png" alt="A seagreen html canvas with a well lit salmon-color octahedron."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking good! But still only looks 2D because we're looking at the mesh straight on.&lt;/p&gt;

&lt;p&gt;We can move the mesh with its &lt;code&gt;rotation&lt;/code&gt; or &lt;code&gt;position&lt;/code&gt; properties, or we can move the camera with its &lt;code&gt;position&lt;/code&gt; property, but to get a full range of interactions we'll add &lt;strong&gt;orbit controls&lt;/strong&gt; &lt;em&gt;after&lt;/em&gt; our camera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="c"&gt;&amp;lt;!-- CAMERA --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;SC.PerspectiveCamera&lt;/span&gt; &lt;span class="na"&gt;near=&lt;/span&gt;&lt;span class="s"&gt;{1}&lt;/span&gt; &lt;span class="na"&gt;far=&lt;/span&gt;&lt;span class="s"&gt;{100}&lt;/span&gt; &lt;span class="na"&gt;fov=&lt;/span&gt;&lt;span class="s"&gt;{55}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;SC.OrbitControls&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;
  &lt;span class="na"&gt;enablePan&lt;/span&gt;
  &lt;span class="na"&gt;enableZoom&lt;/span&gt;
  &lt;span class="na"&gt;enableRotate&lt;/span&gt;
  &lt;span class="na"&gt;enableDamping&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can interact with your scene by clicking and dragging, scrolling to zoom, and right-click and drag to pan. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4jwc2vz812zr6o30iy5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4jwc2vz812zr6o30iy5.gif" alt="A camera rotating around a well lit salmon-color octahedron in front of a seagreen html canvas."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;COOL. But none of your friends know what an octahedron is, so you want to include this scene within the context of a regular website with some words. Svelte (and svelte-cubed) make this incredibly easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the Scene to Your Site
&lt;/h2&gt;

&lt;p&gt;Let's move ALL our code into a new component. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy all the code (script included) in &lt;code&gt;App.svelte&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Click the + icon to create a new file and name it &lt;code&gt;Octo.svelte&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Paste all your code in &lt;code&gt;Octo.svelte&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Delete all the code in &lt;code&gt;App.svelte&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we can't see anything. &lt;code&gt;App.svelte&lt;/code&gt; is the entry point for your application, and it's empty so the page is empty.&lt;/p&gt;

&lt;p&gt;Let's add some markup in &lt;code&gt;App.svelte&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;What is an Octahedron?&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"scene-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;An octahedron is a three-dimensional shape having eight plane faces, especially a regular solid figure with eight equal triangular faces.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll use the "scene-container" div to &lt;em&gt;contain&lt;/em&gt; our scene, and whatever dimensions we set on this container will control our scene dimensions too! Pretty neat.&lt;/p&gt;

&lt;p&gt;Import your &lt;code&gt;Octo.svelte&lt;/code&gt; component and nest it inside the "scene-container" div:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Octo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Octo.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And drop it in the markup like an element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"scene-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Octo&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uh oh, it's taking over the whole page because we haven't styled the "scene-container". In &lt;code&gt;App.svelte&lt;/code&gt; add the style tags under your markup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.scene-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* position relative let's the canvas position itself relative to this container */&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;75%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you go! An informative geometry themed page with a responsive and interactive 3D scene. But you're just getting started. &lt;/p&gt;

&lt;p&gt;Add more shapes, change the camera, add &lt;code&gt;wireframe: true&lt;/code&gt; to the mesh material properties. What if you change the mesh position to animate movement? What if you change the directional light position to change the angle of illumination? What about importing models and animating scenes?&lt;/p&gt;

&lt;p&gt;If you enjoyed this and want to do more experiments, I built a little open source tool to help with some basics that will generate the svelte code for you to build on: &lt;a href="https://sc3-lab.netlify.app/" rel="noopener noreferrer"&gt;https://sc3-lab.netlify.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The plan is to write a couple more of these for movement, transitions, and importing models. Until then, share what you built and be proud of it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmitfdmyot52bprha3sjj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmitfdmyot52bprha3sjj.gif" alt="A robot giving you a thumbs up."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  For Reference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  REPL
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://svelte.dev/repl/71b063fc410543598e8a727999cf7bbe" rel="noopener noreferrer"&gt;https://svelte.dev/repl/71b063fc410543598e8a727999cf7bbe&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  App.svelte
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Octo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Octo.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;What is an Octahedron?&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"scene-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Octo&amp;gt;&amp;lt;/Octo&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;An octahedron is a three-dimensional shape having eight plane faces, especially a regular solid figure with eight equal triangular faces.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.scene-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c"&gt;/* position relative let's the canvas position itself relative to this container */&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;75%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Octo.svelte
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;SC&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte-cubed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;SC.Canvas&lt;/span&gt; &lt;span class="na"&gt;background=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;seagreen&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- LIGHTS --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SC.AmbientLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{.5}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  
  &lt;span class="nt"&gt;&amp;lt;SC.DirectionalLight&lt;/span&gt;
    &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;')}&lt;/span&gt;
    &lt;span class="na"&gt;intensity=&lt;/span&gt;&lt;span class="s"&gt;{.75}&lt;/span&gt;
    &lt;span class="na"&gt;position=&lt;/span&gt;&lt;span class="s"&gt;{[10,&lt;/span&gt; &lt;span class="err"&gt;10,&lt;/span&gt; &lt;span class="err"&gt;10]}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- MESHES --&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;SC.Mesh&lt;/span&gt;
    &lt;span class="na"&gt;geometry=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.OctahedronGeometry&lt;/span&gt;&lt;span class="err"&gt;()}&lt;/span&gt;
    &lt;span class="na"&gt;material=&lt;/span&gt;&lt;span class="s"&gt;{new&lt;/span&gt; &lt;span class="na"&gt;THREE.MeshStandardMaterial&lt;/span&gt;&lt;span class="err"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;color:&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="na"&gt;THREE.Color&lt;/span&gt;&lt;span class="err"&gt;('&lt;/span&gt;&lt;span class="na"&gt;salmon&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;
    &lt;span class="err"&gt;})}&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- CAMERA --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SC.PerspectiveCamera&lt;/span&gt; &lt;span class="na"&gt;near=&lt;/span&gt;&lt;span class="s"&gt;{1}&lt;/span&gt; &lt;span class="na"&gt;far=&lt;/span&gt;&lt;span class="s"&gt;{100}&lt;/span&gt; &lt;span class="na"&gt;fov=&lt;/span&gt;&lt;span class="s"&gt;{55}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;      
  &lt;span class="nt"&gt;&amp;lt;SC.OrbitControls&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;
    &lt;span class="na"&gt;enablePan&lt;/span&gt;
    &lt;span class="na"&gt;enableZoom&lt;/span&gt;
    &lt;span class="na"&gt;enableRotate&lt;/span&gt;
    &lt;span class="na"&gt;enableDamping&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/SC.Canvas&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>svelte</category>
      <category>threejs</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
