-
Notifications
You must be signed in to change notification settings - Fork 29
Description
( just an idea, a discussion, looking for feedbacks )
First, we currently set positions, dimensions, font, colors, for each elements using attributes, but mixed with methods in the same object.
Same thing for the config object which is a mix of different properties with differents usage (i.e element definition vs renderer, or panelSize vs an element name). This currently involves some filters when looping over object attributes in CanvasUI.
Let's take the current buttons example.
const config = {
panelSize: { width: 2, height: 0.5 },
height: 128,
info: { type: "text", position:{ left: 6, top: 6 }, width: 500, height: 58, backgroundColor: "#aaa", fontColor: "#000" },
prev: { type: "button", position:{ top: 64, left: 0 }, width: 64, fontColor: "#bb0", hover: "#ff0", onSelect: onPrev },
stop: { type: "button", position:{ top: 64, left: 64 }, width: 64, fontColor: "#bb0", hover: "#ff0", onSelect: onStop },
next: { type: "button", position:{ top: 64, left: 128 }, width: 64, fontColor: "#bb0", hover: "#ff0", onSelect: onNext },
continue: { type: "button", position:{ top: 70, right: 10 }, width: 200, height: 52, fontColor: "#fff", backgroundColor: "#2659a4", hover: "#3df", onSelect: onContinue },
renderer: this.renderer
}
Below an imaginary refactor, a CSS file and a different CanvasUI setup.
CSS entries. element name are IDs. But we can use classes too. Some littles changes i.e fontColor become color to match css rules.
.button {
color:#bb0;
width:64px;
top:64px;
font-familly:"...";
background-color:#000099;
transition: background-color 0.2s;
}
.button:hover {
background-color:#ff0;
transition: background-color 1s;
}
#info {
left:10px,
top:10px,
width:492px,
height:50px,
background-color:#aaa;
color:#000
}
#continue {
top:70px;
right:70px;
width:200px;
height:50px;
color:#fff;
}
#continue:hover {
color:#0000ff;
}
.red {
background-color:red;
}
Only elements declaration, rather than a mixed object.
Note the "style" attribute to override CSS definitions.
Note the "class" attribute to link custom css properties.
Both "style" and "class" should be like HTML attributes, but parsed by CanvasUI, with properties propagation when object is created.
const elements = {
info: { type: 'text', value:'' },
prev: { type: 'button', value:'...', style:{ left: 0 }, onSelect: onPrev },
stop: { type: 'button', value:'...', style:{ left: 64 }, class:'red', onSelect: onStop },
next: { type: 'button', value:'...', style:{ left: 128 }, onSelect: onNext },
continue: { type: 'button', value:'Continue', onSelect: onContinue },
};
Everything which is not an element attribute should be moved to the config object
const config = {
panelSize: { width:2, height:0.5 } ,
height: 128,
threejs:{
renderer: this.renderer, // mandatory for XR
camera: this.camera, // mandatory when mouse controller used
scene: this.scene // mandatory for scrolling example, needed to add raycaster pointer when select
}
// this is defaults
controller:{
devices:{
mouse:{ enable:true, handler:'follow' },
xr:{ enable:true, raycasterLinesLength:10 }
},
select:{
hover: false, // select once (keyboard behavior),
// hover:true, // trigger select event while raycaster is moving (select+hover) on the element (colorpicker or slider behavior)
repeater:{
// when hover=false, we have a repeater option, delayed trigger select event + repeat.
// usefull to handle "delete" keyboard key, select will repeat until you selectend
timeoutms:100, // 0 mean immediate,
repeatms:20
}
}
},
}
new CanvasUI( elements , config );
Benefits:
- separate UI properties from other settings
- a simple css file can define the look of multiples elements
- realtime editing via chrome console ?
- a step to be "a-frame same logic"
- explorations: custom css attribute ?
- we can parse/implement every interesting css attribute we want (display:none, :hover, transition should be a killer feature
There are multiples ways to read CSS values. One ot them don't need to push something in the DOM Tree, but as some logical limites.
https://stackoverflow.com/questions/324486/how-do-you-read-css-rule-values-with-javascript
I successfully tested the one from Derek Ziemba
//Inside closure so that the inner functions don't need regeneration on every call.
const getCssClasses = (function () {
function normalize(str) {
if (!str) return '';
str = String(str).replace(/\s*([>~+])\s*/g, ' $1 '); //Normalize symbol spacing.
return str.replace(/(\s+)/g, ' ').trim(); //Normalize whitespace
}
function split(str, on) { //Split, Trim, and remove empty elements
return str.split(on).map(x => x.trim()).filter(x => x);
}
function containsAny(selText, ors) {
return selText ? ors.some(x => selText.indexOf(x) >= 0) : false;
}
return function (selector) {
const logicalORs = split(normalize(selector), ',');
const sheets = Array.from(window.document.styleSheets);
const ruleArrays = sheets.map((x) => Array.from(x.rules || x.cssRules || []));
const allRules = ruleArrays.reduce((all, x) => all.concat(x), []);
return allRules.filter((x) => containsAny(normalize(x.selectorText), logicalORs));
};
})();