VueXR is a Vue plugin that let's you project regular DOM components onto augmented reality (AR) markers in real-time. It supports Chrome 99+ based browsers.
Please the official demo at vuexr.technokrat.ch. It is just as easy as:
<ArView>
<ArElement :id="23">
<div class="hello">Hello World!</div>
</ArElement>
</ArView>
With VueXR, you are able to build an AR-Prototype in minutes using your existing 2D web-application. There is no need for you to dive into complex and hard to understand topics such a computer graphics and computer vision – just use your web development skills!
To achieve such functionality, VueXR uses OpenCV.js, CSS-Transforms, Sensor API and Web Workers API on a picture stream from your device's camera. Have a look at our sources or contact me at mw@technokrat.ch or at https://technokrat.ch
- Install
vuexr
package app.use(VueXR)
- Setup VueXR's built in components
<template>
<ArView>
<ArElement :id="23">
<div class="hello">Hello World!</div>
</ArElement>
</ArView>
</template>
- Include
vuexr
CSS-styles in your top package:
@import 'vuexr/style';
- Copy the
worker.*.js
file within thenode_modules/vuexr/assets/
folder into your public path under/assets/
. Example for Vite:
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import {viteStaticCopy } from 'vite-plugin-static-copy'
export default defineConfig({
plugins: [vue(), viteStaticCopy({
targets: [
{
src: 'node_modules/vuexr/dist/assets/*.js',
dest: 'assets'
}
]
})],
})
You can now access your application in a secure context via HTTPS or localhost
(e.g. doing port-forwarding)**
- First install the
vuexr
npm package.
npm install vuexr
# or
yarn add vuexr
- Then add VueXR to your index.js (or index.ts)
import {createApp, } from 'vue';
import {VueXR} from '../../src/vuexr';
import App from '../components/App.vue';
const app = createApp(App);
app.use(VueXR);
app.mount('#app');
- Add the following inside your preferred component (e.g. App.vue)
<template>
<ArView>
<ArElement :id="23">
<div class="hello">Hello World!</div>
</ArElement>
</ArView>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
@import 'vuexr';
.hello {
position: absolute;
box-sizing: border-box;
width: 50px;
height: 50px;
background: rgba(255,255,255,0.9);
padding: 10px;
font-size: 10px;
}
</style>
- Finally you have to copy the WebWorker module
worker.*.js
(e.g.worker.7d65f39e.js
) file within thenode_modules/vuexr/assets/
folder into your public path under/assets/
. The WebWorker can be thought of a script that is run in parallel in the background (to relieve the main thread). It contains a WebAssembly version of the computer vision libraryOpenCV
(roughly 11 MB) which is loaded as soon as<ArView>
is shown the first time. As the WebWorker is run in parallel, the computer vision processing should not impact the overall app performance and responsivity. The WebWorker is imported by VueXR using
const worker = new Worker(new URL("../worker.js", import.meta.url), {type: 'module'});
which leads to a HTTP request similar to http://localhost:1234/assets/worker.7d65f39e.js
when using VueXR as a library.
As there is no mechanism (yet) for the major bundle systems (Vite, Rollup, webpack, etc.) to include or resolve the worker.*.js
file within the public /assets
directory, it has to be copied in a separate step.
Luckily, there are many plugins for that (such as vite-plugin-static-copy
for Vite or CopyWebpackPlugin
for webpack), which not only copy the file for production, but also present it in memory when running a development server.
// vite.config.js
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import {viteStaticCopy } from 'vite-plugin-static-copy'
export default defineConfig({
plugins: [vue(), viteStaticCopy({
targets: [
{
src: 'node_modules/vuexr/dist/assets/*.js',
dest: 'assets'
}
]
})],
})
// vue.config.js
const path = require('path')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
// ...
configureWebpack: {
plugins: [
new CopyWebpackPlugin([
{
from: path.join(__dirname, 'node_modules/vuexr/dist/assets/worker.*.js'),
to: 'assets/'
},
])
]
}
// ...
}
- You are now ready to test the application with a smartphone. **Remember that you have to connect in a secure context via
HTTPS
orlocalhost
(e.g. by using thechrome://inspect
port-forwarding feature) for VueXR to work. Accept the camera's permission request.
For each new device we first need to calibrate the camera (i.e. automatically calculate the focal length), to project our DOM elements with the correct perspective. Just display this chessboard pattern on a different screen, and try to fit all chessboard fields into the camera's view. VueXR will highlight the chessboard's intersection points. Press the red Capture Frame button, and repeat this around eight times for different perspectives. Press the Calibrate button when you are finished. You are now ready to detect the ArUco markers.
You have to use a modern smartphone device, such as a Xiaomi 20K / 9T Pro with MIUI 11, as computer vision takes it's fair share of processing power. Sadly, iOS is not supported due to the limited feature set of Safari.
In general, you only require two new components to use VueXR
<ArView>
is our wrapper around the AR-session. It does initialize all required components for computer vision, camera, and position tracking. It can contain arbitrarily many<ArElement>
's- The
v-slot="{trackedMarkers}"
slot property gives you the current tracked AruCo tags as anArray<string>
. This is useful in case you do not know the AR-tag numbers in advance, and want to instantiate the<ArElement>
in a dynamic way.
- The
<ArElement>
is the container around the content rendered onto a ArUco marker.- The
id
attribute (of typeNumber
) is required and assigns a unique ArUco identifier. - The
timeout
attribute (of typeNumber
in milliseconds, default1000
) sets the time, a<ArElement>
vanishes after it is not detected by the camera anymore - (NOT SUPPORTED) The
markerSize
attribute (of typeNumber
in millimeters, default50
) sets the size of the respective ArUco marker for accurate projection sizing. - The
v-slot="{tracked}"
slot property indicates whether the respective AruCo tag is currently tracked by the camera.
- The
If you need to determine dynamically whether your client supports VueXR before a session is established, use the
$vuexr.check()
promise. E.g. you could write:
<template>
<ArView v-if="supported">
// …
</ArView>
</template>
<script>
import Vue from 'vue'
const App = Vue.extend({
data () {
return {
supported: false
}
},
mounted () {
this.$vuexr.check().then(({supported}) => {
this.supported = supported;
}).catch(() => {
this.supported = false;
})
}
});
export default App;
</script>
VueXR can detect 6x6 ArUco markers up to decimal ID 250
. They are quite robust, and encode orientation and identity
in one. Use this generator webpage to print out a marker and stick it onto your toaster!
An <ArElement>
's origin is based in the middle of the marker. Use absolute positioning or CSS transforms to correctly
align the content.
You might use nested transformations inside your <ArElement>
's content, e.g. transform3d(10px, 20px 30px)
. Ensure to
set the CSS attribute transform-style
to preserve-3d
for all nested elements.
By default, if a <ArElement>
times out due to not being tracked anymore, it will fade out and it's content removed from the DOM.
See (https://vuejs.org/guide/built-ins/transition.html).
If you want to handle things yourself, VueXR offers you a way to check if an <ArElement>
is tracked from inside your
<ArElement>
's content using Scoped Slots
Just use the following pattern to access the tracked
property for a given <ArElement>
:
<ArView>
<ArElement :id="50" v-slot:="{tracked}">
<div class="hello" :class="{tracked: tracked}">
Hello World!
</div>
</ArElement>
</ArView>
Of course you are free to assign tracked
to a sub-components property, use it for conditional rendering, and other
fun stuff (VueXR fully supports the reactive features of Vue).
To animate the content based on the tracked
state, you are free to use CSS transitions and/or animations. E.g. you could
write
<style>
.hello {
position: absolute;
background-color: rgba(255,255,255,0.9);
transition: background-color 0.3s, color 0.3s;
}
.hello.tracked {
background-color: red;
color: white;
}
</style>
One millimeter (mm) in real-world matches one pixel (px
) in your <ArElement>
, plain and simple.
Display this chessboard pattern manually on a different screen, or use the <ArChessboard>
component inside your Vue application. It will show an embedded image of the chessboard pattern.
See the official demo at vuexr.technokrat.ch
Or clone this repository and run
yarn install
yarn run dev
You can now access a demo application of VueXR. To see some AR-content point your camera
onto the AruCo marker with ID 42
. Use this generator webpage to print out a marker or show it on a second screen.
If you just need a web-based ESModule version of OpenCV for your project, you are in luck. The VueXR library is exposing a version of WebAssembly
version with SIMD support under src/opencv/build_simd/opencv.js
. You can import it quite easily:
import cv from 'vuexr/opencv';
async init() {
await cv.ready;
// Your code goes here.
}
init();
- Rewrite JS to TypeScript and cleanup code
- Elaborate documentation on website
- More responsive position tracking
- DOM-Rendering in WebXR API
- Marker Scheme ID Attributes (allowing for future proof support of other marker systems)
- CI and Test Coverage
If you are interested in supporting this project contact me at mw@technokrat.ch
Copyright (c) 2020. Markus Wegmann, Technokrat LLC.
Technokrat LLC and the developers of VueXR are not liable for any damages in relation to the use or installment of VueXR.
Imagine, you could wander through an industrial hall with your smartphone, and directly see real-time sensor readouts hovering in 3D over the machinery. With a simple touch press you then open up a detailed view.
You do not have to scroll through infinite pages of SCADA units on your computer in search for the specific machinery – You are now directly linked via the physical entity itself.
Leaving you more ease-of-access, you benefit from less cognitive demand, so you can do your job more efficient. Maybe you can even identify a failing component in advance, saving your company a lot.
You are a small company offering custom upper-class smarthome & home entertainment solutions. You want to offer your customers a custom User Interface with next-generation features. With VueXR you can combine many already-existing web-solutions into one surface. No problem for VueXR!
Conventional AR requires a lot of expertise in building native smartphone applications for a multitude of platforms, requiring hard to get specialists.
For small and large businesses this poses a very large financial and personnel undertaking, while having bad time to market performance.
In contrast, VueXR allows you to prototype a solution in no time, by leveraging the ease, accessibility, and mutli-platform capabilities of modern web technologies, as well as your existing web codebase: You only have to write your code once!
Why Technokrat?
Technokrat is a full-stack engineering service by ETH-alumni in Zurich, Switzerland, and is the maintainer behind VueXR.
Our strength lies in the combination of research, electronics design, firmware, IoT, computer engineering, manufacturing, and software development.
We can offer you a one-stop experience in upgrading (legacy) setups to AR, or start from the beginning, and consult you and your team in bootstraping and selecting the best competitive solution. We also integrate Web-APIs directly into your existing software (such as REST, GraphQL, SOAP, Swagger, etc.). Just give us a call and we support you with a workshop or MVP in just under six weeks.