work in progress [might break]
This commit is contained in:
parent
774317793b
commit
094a78570b
|
@ -11,9 +11,13 @@ AFRAME.registerComponent('helloworld', {
|
||||||
dom: {
|
dom: {
|
||||||
scale: 3.5,
|
scale: 3.5,
|
||||||
events: ['click','input'],
|
events: ['click','input'],
|
||||||
html: `<div id="hello" class="modal">
|
html: (me) => `
|
||||||
|
<div id="${me.el.uid}" class="modal hello">
|
||||||
|
<div class="top">
|
||||||
|
<div class="title">Hello world</div>
|
||||||
<button class="close">☓</button>
|
<button class="close">☓</button>
|
||||||
<b>Hello world</b>
|
<button class="fold">_</button>
|
||||||
|
</div>
|
||||||
<br><br>
|
<br><br>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Colour</legend>
|
<legend>Colour</legend>
|
||||||
|
@ -25,35 +29,36 @@ AFRAME.registerComponent('helloworld', {
|
||||||
<input id="material-wireframe" type="checkbox" name="wireframe"><label for="material-wireframe"> Wireframe</label><br>
|
<input id="material-wireframe" type="checkbox" name="wireframe"><label for="material-wireframe"> Wireframe</label><br>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Size:</legend>
|
<legend>Size: <span id="value"></span></legend>
|
||||||
<input type="range" min="0.1" max="2" value="1" step="0.01" id="myRange" style="background-color: transparent;">
|
<input type="range" min="0.1" max="2" value="1" step="0.01" id="myRange" style="background-color: transparent;">
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<button onclick="AFRAME.scenes[0].exitVR()" style="display: block;">Exit Immersive</button>
|
<button>hello</button>
|
||||||
</div>`,
|
</div>`,
|
||||||
css: `div{ #hello {position:relative;top:0;width:300px} }`
|
css: `.modal.hello {
|
||||||
|
position:relative;top:0;width:200px
|
||||||
|
foo { /* modern css supported via stylis */ }
|
||||||
|
}`
|
||||||
},
|
},
|
||||||
|
|
||||||
events:{
|
events:{
|
||||||
html: function( ){ console.log("htmlmesh component mounted!") }, // html-component was added to this AFRAME entity
|
html: function( ){ console.log("htmlmesh component mounted!") }, // html-component was added to this AFRAME entity
|
||||||
title: function(e){ this.dom.el.querySelector("b").innerHTML = e.detail.v }, // this.data.title was changed
|
click: function(e){ // a click was detected on this.el.dom or AFRAME entity
|
||||||
click: function(e){ // a click was detected on this.dom.el or AFRAME entity
|
let el = e.detail.target || e.detail.srcElement
|
||||||
if( !e.detail.target ) return
|
if( !el ) return
|
||||||
if( e.detail.target.className == 'close' ){
|
if( el.className.match("fold") ) this.el.toggleFold()
|
||||||
this.dom.el.remove()
|
if( el.className.match("close") ) this.el.close()
|
||||||
this.el.removeAttribute("html")
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
input: function(e){
|
input: function(e){
|
||||||
if( !e.detail.target ) return
|
if( !e.detail.target ) return
|
||||||
if( e.detail.target.id == 'myRange' ) this.data.title = e.detail.target.value // reactive demonstration
|
if( e.detail.target.id == 'myRange' ) this.data.value = e.detail.target.value // reactive demonstration
|
||||||
}
|
},
|
||||||
|
value: function(e){ this.el.dom.querySelector("#value").innerHTML = e.detail.v }, // this.data.title was changed
|
||||||
},
|
},
|
||||||
|
|
||||||
init: function () {
|
init: function () {
|
||||||
this.require( this.dependencies )
|
this.require( this.dependencies )
|
||||||
.then( () => {
|
.then( () => {
|
||||||
document.body.appendChild(this.dom.el)
|
this.el.setAttribute("html",`html:#${this.el.uid}; cursor:#cursor`)
|
||||||
this.el.setAttribute("html",'html:#hello; cursor:#cursor')
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
163
com/app.js
163
com/app.js
|
@ -5,13 +5,14 @@ AFRAME.registerComponent('app', {
|
||||||
"uri":{ type:"string"}
|
"uri":{ type:"string"}
|
||||||
},
|
},
|
||||||
init: function() {
|
init: function() {
|
||||||
this.require([ this.data.uri ])
|
|
||||||
.then( () => {
|
|
||||||
let id = this.data.uri.split("/").pop() // 'a/b/c/mycom.js' => 'mycom.js'
|
let id = this.data.uri.split("/").pop() // 'a/b/c/mycom.js' => 'mycom.js'
|
||||||
let component = id.split(".js").shift() // 'mycom.js' => 'mycom'
|
let component = id.split(".js").shift() // 'mycom.js' => 'mycom'
|
||||||
|
let mount = () => {
|
||||||
let entity = document.createElement("a-entity")
|
let entity = document.createElement("a-entity")
|
||||||
this.el.setAttribute(component,this.data)
|
this.el.setAttribute(component,this.data)
|
||||||
})
|
}
|
||||||
|
if( AFRAME.components[component] || document.head.querySelector(`script#${id}`) ) mount()
|
||||||
|
else this.require([ this.data.uri ]).then( mount ).catch(console.error)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,24 +69,75 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
|
||||||
return function(){
|
return function(){
|
||||||
updateProperties.apply(this,arguments)
|
updateProperties.apply(this,arguments)
|
||||||
if( this.dom && this.data){
|
if( this.dom && this.data){
|
||||||
let reactify = (el,aframe) => new Proxy(this.data,{
|
|
||||||
|
tasks = {
|
||||||
|
|
||||||
|
generateUniqueId: () => {
|
||||||
|
this.el.uid = String(Math.random()).substr(2)
|
||||||
|
return tasks
|
||||||
|
},
|
||||||
|
|
||||||
|
ensureOverlay: () => {
|
||||||
|
let overlay = document.querySelector('#overlay')
|
||||||
|
if( !overlay ){
|
||||||
|
overlay = document.createElement('div')
|
||||||
|
overlay.id = "#overlay"
|
||||||
|
document.body.appendChild(overlay)
|
||||||
|
document.querySelector("a-scene").setAttribute("webxr","overlayElement:#overlay")
|
||||||
|
}
|
||||||
|
tasks.overlay = overlay
|
||||||
|
return tasks
|
||||||
|
},
|
||||||
|
|
||||||
|
createReactiveDOMElement: () => {
|
||||||
|
const reactify = (el,aframe) => new Proxy(this.data,{
|
||||||
get(me,k,v) { return me[k] },
|
get(me,k,v) { return me[k] },
|
||||||
set(me,k,v){
|
set(me,k,v){
|
||||||
me[k] = v
|
me[k] = v
|
||||||
aframe.emit(k,{el,k,v})
|
aframe.emit(k,{el,k,v})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
let el = document.createElement('div')
|
this.el.dom = document.createElement('div')
|
||||||
el.innerHTML = this.dom.html
|
this.el.dom.innerHTML = this.dom.html(this)
|
||||||
this.data = reactify( el, this.el )
|
this.data = reactify( this.dom.el, this.el )
|
||||||
this.dom.el = el.childNodes[0]
|
this.dom.events.map( (e) => this.el.dom.addEventListener(e, (ev) => this.el.emit(e,ev) ) )
|
||||||
this.dom.events.map( (e) => this.dom.el.addEventListener(e, (ev) => this.el.emit(e,ev) ) )
|
return tasks
|
||||||
// add css if any
|
},
|
||||||
|
|
||||||
|
addCSS: () => {
|
||||||
if( this.dom.css && !document.head.querySelector(`style#${this.attrName}`) ){
|
if( this.dom.css && !document.head.querySelector(`style#${this.attrName}`) ){
|
||||||
document.head.innerHTML += `<style id="${this.attrName}">${this.dom.css}</style>`
|
document.head.innerHTML += `<style id="${this.attrName}">${this.dom.css}</style>`
|
||||||
}
|
}
|
||||||
|
return tasks
|
||||||
|
},
|
||||||
|
|
||||||
|
scaleDOMvsXR: () => {
|
||||||
if( this.dom.scale ) this.el.setAttribute('scale',`${this.dom.scale} ${this.dom.scale} ${this.dom.scale}`)
|
if( this.dom.scale ) this.el.setAttribute('scale',`${this.dom.scale} ${this.dom.scale} ${this.dom.scale}`)
|
||||||
//('[helloworld]').object3D.children[0].material.map.magFilter = THREE.NearestFilter
|
return tasks
|
||||||
|
},
|
||||||
|
|
||||||
|
addModalFunctions: () => {
|
||||||
|
this.el.close = () => {
|
||||||
|
this.el.dom.remove()
|
||||||
|
this.el.removeAttribute("html")
|
||||||
|
}
|
||||||
|
this.el.toggleFold = () => {
|
||||||
|
this.el.dom.querySelector(".modal").classList.toggle('fold')
|
||||||
|
this.el.dom.querySelector('.top .fold').innerText = this.el.dom.querySelector('.modal').className.match(/fold/) ? '▢' : '_'
|
||||||
|
}
|
||||||
|
return tasks
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks
|
||||||
|
.generateUniqueId()
|
||||||
|
.ensureOverlay()
|
||||||
|
.addCSS()
|
||||||
|
.createReactiveDOMElement()
|
||||||
|
.scaleDOMvsXR()
|
||||||
|
.addModalFunctions()
|
||||||
|
// finally lets add the bad boy to the DOM
|
||||||
|
tasks.overlay.appendChild(this.el.dom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}( AFRAME.AComponent.prototype.updateProperties)
|
}( AFRAME.AComponent.prototype.updateProperties)
|
||||||
|
@ -93,6 +145,10 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
|
||||||
//
|
//
|
||||||
// base CSS for XRSH apps
|
// base CSS for XRSH apps
|
||||||
//
|
//
|
||||||
|
// limitations / some guidelines for html-mesh compatibility:
|
||||||
|
// * no icon libraries (favicon e.g.)
|
||||||
|
// * 'border-radius: 2px 3px 4px 5px' (applies 2px to all corners)
|
||||||
|
//
|
||||||
document.head.innerHTML += `
|
document.head.innerHTML += `
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
/* CSS reset */
|
/* CSS reset */
|
||||||
|
@ -116,6 +172,8 @@ document.head.innerHTML += `
|
||||||
--xrsh-font-size-1: 14px;
|
--xrsh-font-size-1: 14px;
|
||||||
--xrsh-font-size-2: 17px;
|
--xrsh-font-size-2: 17px;
|
||||||
--xrsh-font-size-3: 21px;
|
--xrsh-font-size-3: 21px;
|
||||||
|
--xrsh-modal-button-bg: #CCC;
|
||||||
|
--xrsh-modal-button-fg: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
a-scene{
|
a-scene{
|
||||||
|
@ -138,21 +196,16 @@ document.head.innerHTML += `
|
||||||
accent-color: var(--xrsh-light-primary);
|
accent-color: var(--xrsh-light-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#overlay{
|
||||||
|
display: flex; /* tile modals */
|
||||||
|
}
|
||||||
|
|
||||||
h1,h2,h3,h4,h5{
|
h1,h2,h3,h4,h5{
|
||||||
color: var(--xrsh-gray);
|
color: var(--xrsh-gray);
|
||||||
}
|
}
|
||||||
h1 { font-size: var(--xrsh-font-size-3); }
|
h1 { font-size: var(--xrsh-font-size-3); }
|
||||||
h2,h3,h4{ font-size: var(--xrsh-font-size-2); }
|
h2,h3,h4{ font-size: var(--xrsh-font-size-2); }
|
||||||
|
|
||||||
.modal{
|
|
||||||
background: #f0f0f0;
|
|
||||||
padding: 20px 20px 10px 20px;
|
|
||||||
border-radius: 15px;
|
|
||||||
display: inline-block;
|
|
||||||
position:relative;
|
|
||||||
z-index:50;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,.btn,input[type=submit]{
|
button,.btn,input[type=submit]{
|
||||||
border-radius:7px;
|
border-radius:7px;
|
||||||
background: var(--xrsh-primary);
|
background: var(--xrsh-primary);
|
||||||
|
@ -160,7 +213,6 @@ document.head.innerHTML += `
|
||||||
transition:0.3s;
|
transition:0.3s;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-block: none;
|
|
||||||
border: none;
|
border: none;
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
}
|
}
|
||||||
|
@ -168,15 +220,74 @@ document.head.innerHTML += `
|
||||||
filter: brightness(1.5);
|
filter: brightness(1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.close{
|
.modal{
|
||||||
background: transparent;
|
background: #f0f0f0;
|
||||||
color: #000;
|
padding: 20px 20px 10px 20px;
|
||||||
|
border-radius: 15px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
position:relative;
|
||||||
|
z-index:50;
|
||||||
|
height:unset;
|
||||||
|
overflow:hidden;
|
||||||
|
margin-left:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.fold {
|
||||||
|
height:22px;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .top{
|
||||||
|
background: var(--xrsh-light-primary);
|
||||||
|
border-radius:15px;
|
||||||
|
position: absolute;
|
||||||
|
z-index:1;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 25px;
|
||||||
|
padding: 13px 10px 1px 14px;
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove this to see why this is a workaround for border-radius bug */
|
||||||
|
.modal .top .title{
|
||||||
|
position: absolute;
|
||||||
|
background: var(--xrsh-light-primary);
|
||||||
|
display: block;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 27px;
|
||||||
|
padding: 0px 0px 0px 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .top button{
|
||||||
|
padding: 5px 7px;
|
||||||
|
background: var(--xrsh-modal-button-bg);
|
||||||
|
color: var(--xrsh-modal-button-fg);
|
||||||
|
font-weight: bold;
|
||||||
float:right;
|
float:right;
|
||||||
|
}
|
||||||
|
.modal .top button:hover{
|
||||||
|
filter: brightness(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .top button.close{
|
||||||
|
background: transparent;
|
||||||
|
display: block;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transform: translate(-4px,-3px) scale(1.3,1);
|
transform: translate(-4px,-3px) scale(1.5,1);
|
||||||
margin-left: 20px;
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .top button.fold{
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
margin-left: 30px;
|
||||||
|
transform: scale(1.2) translate(0px,-6px);
|
||||||
}
|
}
|
||||||
|
|
||||||
legend{
|
legend{
|
||||||
|
|
Loading…
Reference in New Issue