aframe-gui
Version:
A-Frame GUI components
221 lines (194 loc) • 10.1 kB
JavaScript
AFRAME.registerComponent('gui-icon-label-button', {
schema: {
on: {default: 'click'},
toggle: {type: 'boolean', default: false},
toggleState: {type: 'boolean', default: false},
icon: {type: 'string', default: 'f0f3'},
iconActive: {type: 'string', default: ''},
iconFontSize: {type: 'number', default: 0.35},
iconFont: {type: 'string', default: 'assets/fonts/fa-regular-400.ttf'},
value: {type: 'string', default: ''},
fontSize: {type: 'number', default: 0.2},
fontFamily: {type: 'string', default: ''},
fontColor: {type: 'string', default: key_offwhite},
borderColor: {type: 'string', default: key_offwhite},
backgroundColor: {type: 'string', default: key_grey},
hoverColor: {type: 'string', default: key_grey_dark},
activeColor: {type: 'string', default: key_orange},
},
init: function() {
var data = this.data;
var el = this.el;
var guiItem = el.getAttribute("gui-item");
this.guiItem = guiItem;
var toggleState = this.toggleState = data.toggle;
var guiInteractable = el.getAttribute("gui-interactable");
this.guiInteractable = guiInteractable;
//fallback for old font-sizing
if(data.iconFontSize > 20) { // 150/750
var newSize = data.iconFontSize/750;
data.iconFontSize = newSize;
}
if(data.fontSize > 20) { // 150/750
var newSize = data.fontSize/750;
data.fontSize = newSize;
}
el.setAttribute('geometry', `primitive: plane; height: ${guiItem.height}; width: ${guiItem.width};`);
el.setAttribute('material', `shader: flat; side:front; color:${data.backgroundColor};`);
var buttonContainer = document.createElement("a-entity");
buttonContainer.setAttribute('geometry', `primitive: box; width: ${guiItem.width}; height: ${guiItem.height}; depth: 0.02;`);
buttonContainer.setAttribute('material', `shader: flat; opacity: 1; side:double; color: ${data.borderColor}`);
buttonContainer.setAttribute('rotation', '0 0 0');
buttonContainer.setAttribute('position', '0 0 0.01');
el.appendChild(buttonContainer);
var buttonEntity = document.createElement("a-entity");
buttonEntity.setAttribute('geometry', `primitive: box; width: ${(guiItem.width-0.025)}; height: ${(guiItem.height-0.025)}; depth: 0.04;`);
buttonEntity.setAttribute('material', `shader: flat; opacity: 1; side:double; color: ${data.toggleState ? data.activeColor : data.backgroundColor}`);
buttonEntity.setAttribute('rotation', '0 0 0');
buttonEntity.setAttribute('position', '0 0 0.02');
el.appendChild(buttonEntity);
this.buttonEntity = buttonEntity;
this.setIcon(data.icon);
if(data.value != ''){ this.setText(data.value) }
el.addEventListener('mouseenter', function(event) {
buttonEntity.removeAttribute('animation__leave');
if (!(data.toggle)) {
buttonEntity.setAttribute('animation__enter', `property: material.color; from: ${data.backgroundColor}; to:${data.hoverColor}; dur:200;`);
}
});
el.addEventListener('mouseleave', function(event) {
if (!(data.toggle)) {
buttonEntity.removeAttribute('animation__click');
buttonEntity.setAttribute('animation__leave', `property: material.color; from: ${data.hoverColor}; to:${data.backgroundColor}; dur:200; easing: easeOutQuad;`);
}
buttonEntity.removeAttribute('animation__enter');
});
el.addEventListener(data.on, function(event) {
if (!(data.toggle)) { // if not toggling flashing active state
buttonEntity.setAttribute('animation__click', `property: material.color; from: ${data.activeColor}; to:${data.backgroundColor}; dur:400; easing: easeOutQuad;`);
}else{
var guiButton = el.components['gui-button']
// console.log("about to toggle, current state: " + guiButton.data.toggleState);
guiButton.setActiveState(!guiButton.data.toggleState);
// buttonEntity.setAttribute('material', 'color', data.activeColor);
}
var clickActionFunctionName = guiInteractable.clickAction;
// console.log("in button, clickActionFunctionName: "+clickActionFunctionName);
// find object
var clickActionFunction = window[clickActionFunctionName];
//console.log("clickActionFunction: "+clickActionFunction);
// is object a function?
if (typeof clickActionFunction === "function") clickActionFunction(event);
});
////WAI ARIA Support
el.setAttribute('role', 'button');
},
play: function () {
},
update: function (oldData) {
console.log("In button update, toggle: "+this.toggleState);
var data = this.data;
var el = this.el;
if(this.iconEntity){
console.log("has iconEntity: "+this.iconEntity);
var oldEntity = this.iconEntity;
oldEntity.parentNode.removeChild(oldEntity);
this.setIcon(this.data.icon);
}else{
console.log("no iconEntity!");
}
if(this.textEntity){
console.log("has textEntity: "+this.textEntity);
var oldEntity = this.textEntity;
oldEntity.parentNode.removeChild(oldEntity);
this.setText(this.data.value);
}else{
console.log("no textEntity!");
}
},
setActiveState: function (activeState) {
// console.log("in setActiveState function, new state: " + activeState);
this.data.toggleState = activeState;
if (!activeState) {
console.log('not active, about to set background color');
this.buttonEntity.setAttribute('material', 'color', this.data.backgroundColor);
} else {
console.log('active, about to set active color');
this.buttonEntity.setAttribute('material', 'color', this.data.activeColor);
}
},
setIcon: function (unicode) {
var hex = parseInt(unicode, 16);
var char = String.fromCharCode(hex);
var iconEntity = document.createElement("a-entity");
var iconEntityX = 0;
if(this.data.value != ''){
iconEntityX = -this.guiItem.width*0.5 + this.guiItem.height*0.5;
}
this.iconEntity = iconEntity;
iconEntity.setAttribute('troika-text', `value:${char};
align:center;
anchor:center;
baseline:center;
color:${this.data.fontColor};
font:${this.data.iconFont};
fontSize:${this.data.iconFontSize};
depthOffset:1;
`);
iconEntity.setAttribute('position', `${iconEntityX} 0 0.05`); // 0.05 y axis adjustment for fontawesome
// textEntity.setAttribute('troika-text-material', `shader: flat;`);
this.el.appendChild(iconEntity);
},
setText: function (newText) {
var textEntityX = this.guiItem.height - this.guiItem.width*0.5;
var textEntity = document.createElement("a-entity");
this.textEntity = textEntity;
textEntity.setAttribute('troika-text', `value: ${newText};
align:left;
anchor:left;
baseline:center;
letterSpacing:0;
color:${this.data.fontColor};
font:${this.data.fontFamily};
fontSize:${this.data.fontSize};
depthOffset:1;
maxWidth:${this.guiItem.width/1.05};
`);
textEntity.setAttribute('position', `${textEntityX} 0 0.05`);
// textEntity.setAttribute('troika-text-material', `shader: flat;`);
this.el.appendChild(textEntity);
},
});
AFRAME.registerPrimitive( 'a-gui-icon-label-button', {
defaultComponents: {
'gui-interactable': { },
'gui-item': { type: 'icon-label-button' },
'gui-icon-label-button': { }
},
mappings: {
//gui interactable general
'onclick': 'gui-interactable.clickAction',
'onhover': 'gui-interactable.hoverAction',
'key-code': 'gui-interactable.keyCode',
//gui item general
'width': 'gui-item.width',
'height': 'gui-item.height',
'margin': 'gui-item.margin',
//gui button specific
'on': 'gui-icon-label-button.on',
'font-color': 'gui-icon-label-button.fontColor',
'font-family': 'gui-icon-label-button.fontFamily',
'font-size': 'gui-icon-label-button.fontSize',
'border-color': 'gui-icon-label-button.borderColor',
'background-color': 'gui-icon-label-button.backgroundColor',
'hover-color': 'gui-icon-label-button.hoverColor',
'active-color': 'gui-icon-label-button.activeColor',
'icon': 'gui-icon-label-button.icon',
'icon-active': 'gui-icon-label-button.iconActive',
'icon-font': 'gui-icon-label-button.iconFont',
'icon-font-size': 'gui-icon-label-button.iconFontSize',
'value': 'gui-icon-label-button.value',
'toggle': 'gui-icon-label-button.toggle',
'toggle-state': 'gui-icon-label-button.toggleState'
}
});