Dan W
Dan W

Reputation: 138

Nuxt & A-Frame VR

Has anyone else tried to mix A-Frame VR with Nuxt.js? I get the error "Window is not defined".

I have so far

  1. Installed A-Frame via NPM

  2. Created a plugin "plugins/aframe.js" with the following

import Vue from 'vue'
import aframe from 'aframe'
Vue.use(aframe)
  1. Updated nuxt.config.js
plugins: [
    { src: '@/plugins/aframe.js', ssr: false }
  ],
  1. Created a component "components/Aframe.vue"
<template>
  <a-scene vr-mode-ui="enabled: false">
      <a-entity position="0 0 0">
        <a-camera></a-camera>
      </a-entity>
      <a-entity
        geometry="primitive: torusKnot;"
        scale="2 2 2"
        position="0 1.5 -5"
        rotation="0 45 0"
        material="color:#BBBBBB"
        wireframe
      >
        <a-animation easing="linear" attribute="rotation" repeat="indefinite" dur="30000" to="0 405 0"></a-animation>
      </a-entity>
      <a-sky color="#FDFDFD"></a-sky>
    </a-scene>
</template>
if (process.client) {
  Vue.use(require('aframe'))
}
export default {
  created () {
    aframe.registerComponent('wireframe', {
      dependencies: ['material'],
      init () {
        this.el.components.material.material.wireframe = true
      }
    })
  }
}

And included the component in my default layout

<Aframe /> 
import Aframe from 'aframe'
export default {
  components: {
    Aframe
  },

Upvotes: 1

Views: 1366

Answers (2)

Brian Lawrence
Brian Lawrence

Reputation: 21

I found a clean way to do this using SPA Mode. You will need to create a module that intercepts the router request to the page containing your A-Frame code. This method will make it so A-Frame is only loaded client-side and thus A-Frame will have access to client-side only objects like window.

Step 1: Create a new module, name it whatever you want and make sure it intercepts the call to your page - in this example, the page is named vrdemo.vue under pages. Make sure to put your module in the correct module folder: root->modules->navmodules.js

export default function () {
  this.nuxt.hook('render:setupMiddleware', (app) => {
    app.use('/vrdemo', (req, res, next) => { //Do NOT load vrdemo on the server-side due to use of client only a-frame JS libraries
    res.spa = true
    next()
    })
  })
}

Step 2: Register the module in nuxt.config

 modules: [ '~/modules/navmodule'],

Step 3: Import A-Frame in the page your module is intercepting

<template>
    //use A-Frame
</template>
<script>
  import aframe from "aframe";
  export default {
   //stuff
  };
</script>

I additionally made some components that use A-Frame, as long as I call the component from this page, the A-Frame script is loaded and I can use it.

You will need to make sure you have installed A-Frame (npm install aframe) into your project using npm or yarn for this to work. Good Luck!

Upvotes: 1

Dan W
Dan W

Reputation: 138

For anyone else struggling with this here is one way that seems to work.

In nuxt.config.js add a-frame vr as a script tag

script: [
  {
    src: 'https://aframe.io/releases/0.7.1/aframe.min.js'
  }
]

Then in your component add the a-frame scene as data string

export default {
  name: 'afvr',
  data () {
    return {
      aframes: [
        {
          scene: '<a-scene vr-mode-ui="enabled: false" embedded><a-entity position="0 -1 3" scale="0.5 0.5 0.5"><a-camera zoom="0.8" fov="80" near="0.001" far="50"></a-camera></a-entity><a-torus-knot color="#e1e1e1" segments-tubular="124" radius="1" radius-tubular="0.1" wireframe="true"><a-animation easing="linear" attribute="rotation" repeat="indefinite" dur="30000" to="360 360 360"></a-animation></a-torus-knot></a-scene>',
          id: 1
        }
      ]
    }
  }
}

Then render it in the template as raw HTML

<div class="aframe" v-for="aframe in aframes" :key="aframe.id" v-html="aframe.scene" />

Does the trick

Upvotes: 1

Related Questions