Vue

by Erick Petrucelli

HTML

<script src="https://unpkg.com/three"></script>
<script src="https://unpkg.com/vue-gl"></script>
<div id="app">
  <nav>
    <a v-for="n in 3" :key="n" :href="isExample(n) ? null : `#${n}`" :class="{ disabled: isExample(n) }" @click.prevent="showExample(n)">
      Example {{ n }}
    </a>
  </nav>

  <main>
    <div v-show="isExample(1)">
      <vgl-renderer name="renderer" scene="scene" camera="camera" antialias>
        <vgl-box-geometry name="box" />
        <vgl-scene name="scene">
          <vgl-mesh geometry="box" />
        </vgl-scene>
        <vgl-perspective-camera name="camera" orbit-position="3 1 0.5" />
      </vgl-renderer>
    </div>

    <div v-show="isExample(2)">
      <vgl-renderer name="renderer" scene="scene" camera="camera" antialias>
        <vgl-box-geometry name="box" />
        <vgl-mesh-standard-material name="material" />
        <vgl-scene name="scene">
          <vgl-mesh geometry="box" material="material" />
          <vgl-directional-light name="light" position="1 2 3" />
        </vgl-scene>
        <vgl-perspective-camera name="camera" orbit-position="3 1 0.5" />
      </vgl-renderer>
    </div>

    <div v-show="isExample(3)">
      <vgl-renderer name="renderer" scene="scene" camera="camera" antialias>
        <vgl-scene name="scene" background-color="#999" fog="#999 0.1 20">
          <vgl-box-geometry name="boxGeometry" />
          <vgl-mesh-standard-material name="boxMaterial" />
          <vgl-mesh geometry="boxGeometry" material="boxMaterial" cast-shadow receive-shadow position="0 0.5 0" :rotation="`0 ${boxRotationY} 0 ZYX`" />

          <vgl-box-geometry name="groundGeometry" width="50" depth="50" height="0.1" />
          <vgl-mesh-phong-material name="groundMaterial" color="#666" />
          <vgl-mesh geometry="groundGeometry" material="groundMaterial" cast-shadow receive-shadow position="0 -0.5 0"/>

          <vgl-hemisphere-light name="hemisphere" color="#fff" ground-color="#666" intensity="0.2" />
         ...

CSS

html, body {
  height: 100vh;
}

body {
  background: #20262e;
  font-family: Helvetica, Arial, sans-serif;
  margin: 0;
  padding: 0;
}

#app {
  box-sizing: border-box;
  height: 100%;
  padding: 1rem;
  display: flex;
  flex-flow: column;
  gap: 0.5rem;
}

nav {
  flex: 0;
  display: flex;
  gap: 0.5rem;
}

a {
  padding: 0.25rem;
  text-decoration: none;
  color: #2795ee;
}

a.disabled {
  opacity: 0.3;
  cursor: default;
}

main {
  flex: 1;
  display: flex;
}

main > div {
  display: flex;
  flex-flow: column;
  gap: 1rem;
}

main > div > *:first-child {
  /* height: 100%; */ /*  fluid size not working */
  /* height: 300px; only works when fixing vgl-renderer in pixels */
  line-height: 0;
  height: 100%;
}

.fade-enter-active, .fade-leave-active {
  transition: opacity 0.25s ease-in-out;
}

.fade-enter, .fade-leave-to {
  opacity: 0;
}

Vue

Object.keys(VueGL).forEach((name) => {
  Vue.component(name, VueGL[name]);
});

new Vue({
  el: "#app",
  data: {
  	example: 1,
    boxRotationY: 0,
	},
  methods: {
  	showExample (example) {
    	this.example = example
    },

    isExample (example) {
    	return (this.example === example)
    }
  }
})