Last active
September 18, 2018 03:09
-
-
Save richplastow/30172223a074110eadf2ca752b48a040 to your computer and use it in GitHub Desktop.
Vue plus A-Frame tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en-GB"> | |
<head> | |
<!-- Technical meta --> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |
<!-- Search engine meta --> | |
<title>Vue plus A-Frame test 1</title> | |
<script src="//unpkg.com/vue"></script> | |
<script src="//unpkg.com/aframe"></script> | |
<script src="//stemkoski.github.io/Three.js/js/polyhedra.js"></script> | |
<script> | |
AFRAME.registerComponent('ui-event', { | |
init: function () { | |
var el = this.el // <a-entity> | |
var listener = function (evt) { | |
window.dispatchEvent( | |
new CustomEvent('ui-event', { detail: { el:el, type:evt.type } }) | |
) | |
} | |
el.addEventListener('mouseenter', listener) | |
el.addEventListener('mouseleave', listener) | |
} | |
}) | |
AFRAME.registerGeometry('example', { | |
schema: { | |
vertices: { | |
default: ['-10 10 0', '-10 -10 0', '10 -10 0'], | |
} | |
}, | |
init: function (data) { | |
var geometry = new THREE.Geometry(); | |
geometry.vertices = data.vertices.map(function (vertex) { | |
var points = vertex.split(' ').map(function(x){return parseInt(x);}); | |
return new THREE.Vector3(points[0], points[1], points[2]); | |
}); | |
geometry.computeBoundingBox(); | |
geometry.faces.push(new THREE.Face3(0, 1, 2)); | |
geometry.mergeVertices(); | |
geometry.computeFaceNormals(); | |
geometry.computeVertexNormals(); | |
this.geometry = geometry; | |
} | |
}) | |
</script> | |
</head> | |
<body style="background:#000"> | |
<h2 style="position:fixed; left:0.5em; z-index:999; color:#fff; font-family:sans-serif"> | |
Vue plus A-Frame test 1:<br> | |
Use the arrow keys to navigate.<br> | |
Shapes react to white-circle rollover. | |
</h2> | |
<a-scene> | |
<a-sky color="#222"></a-sky> | |
<a-camera> | |
<a-cursor color="white"></a-cursor> | |
</a-camera> | |
<a-entity v-for="(poly, i) in polys"> | |
<a-entity | |
v-bind:rotation="poly.arc"> | |
<a-entity | |
ui-event | |
v-bind:id="i"> | |
<a-entity | |
v-bind:geometry="poly.geometry" | |
v-bind:material="poly.material" | |
v-bind:scale ="poly.scale" | |
v-bind:rotation="poly.rotation" | |
position="0 2 -3" | |
></a-entity> | |
</a-entity> | |
<a-entity | |
position="0 1.25 -2.4" | |
v-bind:scale="poly.hover"> | |
<a-entity | |
v-bind:text="poly.name" | |
></a-entity> | |
</a-entity> | |
</a-entity> | |
</a-entity> | |
</a-scene> | |
<script>!function () { | |
const colors = [ | |
'#123456' | |
, '#987654' | |
, '#891234' | |
, '#678912' | |
, '#219876' | |
] | |
const polys = [ | |
{ | |
name: 'Cube' | |
, geometry: 'primitive: box; width: 1; height: 1; depth: 1' | |
} | |
, { | |
name: 'Dodecahedron' | |
, geometry: 'primitive: dodecahedron; radius: 0.6' | |
} | |
, { | |
name: 'Octahedron' | |
, geometry: 'primitive: octahedron; radius: 0.6' | |
} | |
, { | |
name: 'Tetrahedron' | |
, geometry: 'primitive: tetrahedron; radius: 0.6' | |
} | |
, { | |
name: 'Example' | |
, geometry: 'primitive: example; vertices: 1 1 -3, 3 1 -3, 2 2 -3' | |
} | |
] | |
for (let i=0, poly; poly=polys[i]; i++) { | |
poly.arc = `0 ${30*i} 0` | |
poly.rotation = '0 -15 0' | |
poly.hover = '0 0 0' | |
poly.scale = '1 1 1' | |
poly.scaleTarget = '1 1 1' | |
poly.material = `flatShading: true; color: ${colors[i]}` | |
poly.name = `color: white; align: center; width: 3; value: ${poly.name};` | |
} | |
Vue.config.ignoredElements = [ | |
'a-scene', 'a-sky', 'a-camera', 'a-cursor', 'a-entity' | |
] | |
const app = new Vue({ | |
el: 'a-scene' | |
, data: { polys } | |
}) | |
//// Deal with UI events. | |
window.addEventListener('ui-event', function (evt) { | |
if (! evt.detail || ! evt.detail.el || null == evt.detail.el.id) return | |
const el = evt.detail.el | |
, id = +el.id | |
, type = evt.detail.type | |
, poly = app.polys[id] | |
if ('mouseenter' === type) { | |
poly.scaleTarget = '1.2 1.2 1.2' | |
poly.hover = '1 1 1' | |
} | |
if ('mouseleave' === type) { | |
poly.scaleTarget = '1 1 1' | |
poly.hover = '0 0 0' | |
} | |
}) | |
//// Perform tweening and animation. | |
function step () { | |
for (let i=0, poly; poly=app.polys[i]; i++) { | |
//// Rotate hovered poly. | |
if ('1 1 1' === poly.hover) { | |
const rotation = poly.rotation.split(' ') | |
rotation[1] = ++ rotation[1] % 360 | |
poly.rotation = rotation.join(' ') | |
} | |
//// Tween scale. | |
if (poly.scale !== poly.scaleTarget) { | |
const value = poly.scale.split(' ').map(Number) | |
, valueTarget = poly.scaleTarget.split(' ').map(Number) | |
, diff = [ | |
Math.abs(valueTarget[0] - value[0]) | |
, Math.abs(valueTarget[1] - value[1]) | |
, Math.abs(valueTarget[2] - value[2]) | |
] | |
if ( | |
0.01 > diff[0] | |
&& 0.01 > diff[1] | |
&& 0.01 > diff[2] | |
) { | |
poly.scale = poly.scaleTarget | |
} else { | |
value[0] = (value[0] * 3 + valueTarget[0]) / 4 | |
value[1] = (value[1] * 3 + valueTarget[1]) / 4 | |
value[2] = (value[2] * 3 + valueTarget[2]) / 4 | |
poly.scale = value.join(' ') | |
} | |
} | |
} | |
window.requestAnimationFrame(step) | |
} | |
window.requestAnimationFrame(step) | |
//// See view-source:https://stemkoski.github.io/Three.js/Polyhedra.html | |
function polyhedronDataToMesh(data) | |
{ | |
var polyhedron = new THREE.Object3D(); | |
// convert vertex data to THREE.js vectors | |
var vertex = [] | |
for (var i = 0; i < data.vertex.length; i++) | |
vertex.push( new THREE.Vector3( data.vertex[i][0], data.vertex[i][1], data.vertex[i][2] ).multiplyScalar(100) ); | |
var vertexGeometry = new THREE.SphereGeometry( 6, 12, 6 ); | |
var vertexMaterial = new THREE.MeshLambertMaterial( { color: 0x222244 } ); | |
var vertexSingleMesh = new THREE.Mesh( vertexGeometry ); | |
var vertexAmalgam = new THREE.Geometry(); | |
for (var i = 0; i < data.vertex.length; i++) | |
{ | |
var vMesh = vertexSingleMesh.clone(); | |
vMesh.position = vertex[i]; | |
THREE.GeometryUtils.merge( vertexAmalgam, vMesh ); | |
} | |
var vertexMesh = new THREE.Mesh( vertexAmalgam, vertexMaterial ); | |
polyhedron.add( vertexMesh ); | |
// convert edge data to cylinders | |
var edgeMaterial = new THREE.MeshLambertMaterial( {color: 0x666666} ); | |
var edgeAmalgam = new THREE.Geometry(); | |
for (var i = 0; i < data.edge.length; i++) | |
{ | |
var index0 = data.edge[i][0]; | |
var index1 = data.edge[i][1]; | |
var eMesh = cylinderMesh( vertex[index0], vertex[index1], edgeMaterial ); | |
THREE.GeometryUtils.merge( edgeAmalgam, eMesh ); | |
} | |
var edgeMesh = new THREE.Mesh( edgeAmalgam, edgeMaterial ); | |
polyhedron.add( edgeMesh ); | |
// convert face data to a single (triangulated) geometry | |
var faceMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors, side: THREE.FrontSide, transparent:parameters.transparent, opacity:0.8 } ); | |
var faceColors = | |
{ | |
3: new THREE.Color( 0xcc0000 ), | |
4: new THREE.Color( 0x00cc00 ), | |
5: new THREE.Color( 0x0000cc ), | |
6: new THREE.Color( 0xcccc00 ), | |
7: new THREE.Color( 0x999999 ), | |
8: new THREE.Color( 0x990099 ), | |
9: new THREE.Color( 0xff6600 ), | |
10: new THREE.Color( 0x6666ff ) | |
}; | |
var geometry = new THREE.Geometry(); | |
geometry.vertices = vertex; | |
var faceIndex = 0; | |
for (var faceNum = 0; faceNum < data.face.length; faceNum++) | |
{ | |
for (var i = 0; i < data.face[faceNum].length - 2; i++) | |
{ | |
geometry.faces[faceIndex] = new THREE.Face3( data.face[faceNum][0], data.face[faceNum][i+1], data.face[faceNum][i+2] ); | |
geometry.faces[faceIndex].color = faceColors[data.face[faceNum].length]; | |
faceIndex++; | |
} | |
} | |
geometry.computeFaceNormals(); | |
geometry.computeVertexNormals(); | |
faces = new THREE.Mesh(geometry, faceMaterial); | |
faces.scale.multiplyScalar(1.01); | |
polyhedron.add(faces); | |
var interiorMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors, side: THREE.BackSide } ); | |
var interiorFaces = new THREE.Mesh(geometry, interiorMaterial); | |
interiorFaces.scale.multiplyScalar(0.99); | |
polyhedron.add( interiorFaces ); | |
return polyhedron; | |
} | |
}()</script> | |
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en-GB"> | |
<head> | |
<!-- Technical meta --> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |
<!-- Search engine meta --> | |
<title>Vue plus A-Frame test 2</title> | |
<script src="//unpkg.com/vue"></script> | |
<script src="//unpkg.com/aframe"></script> | |
<script> | |
AFRAME.registerComponent('ui-event', { | |
init: function () { | |
var el = this.el // <a-entity> | |
var listener = function (evt) { | |
window.dispatchEvent( | |
new CustomEvent('ui-event', { detail: { el:el, type:evt.type } }) | |
) | |
} | |
el.addEventListener('mouseenter', listener) | |
el.addEventListener('mouseleave', listener) | |
el.addEventListener('mousedown' , listener) | |
el.addEventListener('mouseup' , listener) | |
} | |
}) | |
//// Deal with UI events. | |
window.addEventListener('ui-event', function (evt) { | |
if (! evt.detail || ! evt.detail.el || null == evt.detail.el.id) return | |
const el = evt.detail.el | |
, id = +el.id | |
, type = evt.detail.type | |
if ('mouseenter' === type) { | |
window.data.color = '#' | |
+ (~~(Math.random()*5+5)) | |
+ (~~(Math.random()*5+5)) | |
+ (~~(Math.random()*2)) | |
} else if ('mouseleave' === type) { | |
window.data.color = '#' | |
+ (~~(Math.random()*2)) | |
+ (~~(Math.random()*5+5)) | |
+ (~~(Math.random()*5+5)) | |
} else if ('mousedown' === type) { | |
var num = ~~(Math.random()*5+5) | |
window.data.color = '#' | |
+ num | |
+ num | |
+ num | |
} else if ('mouseup' === type) { | |
window.data.color = '#' | |
+ (~~(Math.random()*5+5)) | |
+ (~~(Math.random()*2)) | |
+ (~~(Math.random()*5+5)) | |
} | |
}) | |
</script> | |
</head> | |
<body style="background:#000"> | |
<h2 style="position:fixed; left:0.5em; z-index:999; color:#fff; font-family:sans-serif"> | |
Vue plus A-Frame test 2:<br> | |
Mouse-drag to look around.<br> | |
Shape reacts to white-circle rollover AND ALSO mouse-cursor rollover.<br> | |
Also, mouse-down/up-anywhere when the white-circle is over the shape, <br> | |
<em>AND</em> directly mouse-down/up on the shape. | |
</h2> | |
<a-scene cursor="rayOrigin: mouse"> | |
<a-sky color="#222"></a-sky> | |
<a-camera position="0 -1 2"> | |
<a-cursor color="white"></a-cursor> | |
</a-camera> | |
<a-box ui-event v-bind:color="color"></a-box> | |
</a-scene> | |
<script>!function () { | |
Vue.config.ignoredElements = [ | |
'a-scene', 'a-sky', 'a-camera', 'a-cursor', 'a-box' | |
] | |
Vue.component('my-thing', { | |
template: '<div>A custom component!</div>' | |
}) | |
window.data = { color: 'blue' } | |
const app = new Vue({ | |
el: 'a-box' | |
, data: window.data | |
}) | |
}()</script> | |
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en-GB"> | |
<head> | |
<!-- Technical meta --> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |
<!-- Search engine meta --> | |
<title>Vue plus A-Frame test 3</title> | |
<script src="//unpkg.com/vue"></script> | |
<script src="//unpkg.com/aframe"></script> | |
<script src="//unpkg.com/aframe-html-shader@0.2.0/dist/aframe-html-shader.min.js"></script> | |
<script> | |
AFRAME.registerComponent('ui-event', { | |
init: function () { | |
var el = this.el // <a-entity> | |
var listener = function (evt) { | |
window.dispatchEvent( | |
new CustomEvent('ui-event', { detail: { el:el, type:evt.type } }) | |
) | |
} | |
el.addEventListener('mouseenter', listener) | |
el.addEventListener('mouseleave', listener) | |
} | |
}) | |
AFRAME.registerGeometry('example', { | |
schema: { | |
vertices: { | |
default: ['-10 10 0', '-10 -10 0', '10 -10 0'], | |
} | |
}, | |
init: function (data) { | |
var geometry = new THREE.Geometry(); | |
geometry.vertices = data.vertices.map(function (vertex) { | |
var points = vertex.split(' ').map(function(x){return parseInt(x);}); | |
return new THREE.Vector3(points[0], points[1], points[2]); | |
}); | |
geometry.computeBoundingBox(); | |
geometry.faces.push(new THREE.Face3(0, 1, 2)); | |
geometry.mergeVertices(); | |
geometry.computeFaceNormals(); | |
geometry.computeVertexNormals(); | |
this.geometry = geometry; | |
} | |
}) | |
</script> | |
</head> | |
<body style="background:#000"> | |
<h2 style="position:fixed; left:410px; z-index:999; color:#fff; font-family:sans-serif"> | |
Vue plus A-Frame test 3:<br> | |
Clicking the buttons makes Vue change the 2D square.<br> | |
The ‘aframe-html-shader’ component converts the 2D square to a 3D material.<br><br> | |
<button | |
style="font-size:1em;" | |
onclick="window.data.color='#'+(~~(Math.random()*10))+(~~(Math.random()*10))+(~~(Math.random()*10))"> | |
Random Color</button><br><br> | |
<button | |
style="font-size:1em;" | |
onclick="window.data.text=String.fromCharCode( | |
~~(Math.random()*26+65),~~(Math.random()*26+65),~~(Math.random()*26+65) | |
)">Random Text</button> | |
</h2> | |
<div | |
style="width:400px; height:400px; position:fixed; left:0; top:0; | |
z-index:50; overflow:hidden; text-align:center;"> | |
<div id="htmlElement" | |
v-bind:style="'background:'+color+'; color:#fff; height:400px; font-size:72px'"> | |
<br>{{ text }} | |
</div> | |
</div> | |
<a-scene> | |
<a-sky color="#222"></a-sky> | |
<a-camera position="0 -1 2"></a-camera> | |
<a-entity laser-controls line="color: red; opacity: 0.75"></a-entity> | |
<a-entity geometry="primitive:box" material="shader:html; target:#htmlElement; fps:60"></a-entity> | |
</a-scene> | |
<script>!function () { | |
Vue.config.ignoredElements = [ | |
'a-scene', 'a-sky', 'a-camera', 'a-cursor', 'a-entity' | |
] | |
Vue.component('my-thing', { | |
template: '<div>A custom component!</div>' | |
}) | |
window.data = { | |
color: '#890' | |
, text: 'Ready' | |
} | |
const app = new Vue({ | |
el: '#htmlElement' | |
, data: window.data | |
}) | |
}()</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment