muigui ⍺
What / Why?
Ranges:
Like <input type="range">
, manipulates a number with optional conversions.
const s = {
value1: 40,
value2: 50,
value3: 80,
value4: 60,
value5: 65,
angleRad: Math.PI * 0.25,
};
const gui = new GUI();
gui.add(s, 'value1', 0, 100); // 0 to 100
gui.add(s, 'value2', 0, 100, 1); // 0 to 100 by in steps of 1
gui.add(s, 'value3', 0, 100, 5); // 0 to 100 by steps of 5
GUI.makeMinMaxPair(gui, s, 'value4', 'value5', {
min: 0, max: 100, minRange: 5,
});
const degToRad = d => d * Math.PI / 180;
const radToDeg = r => r * 180 / Math.PI;
gui.add(s, 'angleRad', {
min: -360, max: 360, step: 1,
converters: {
to: radToDeg,
from: v => [true, degToRad(v)]},
});
Dropdowns:
Like <select>
, lets you pick one of many options.
const s = {
byIndex: 2,
byString: 'dog',
byKeyValue: 0.5,
byKVArray: 2,
};
const gui = new GUI();
gui.add(s, 'byIndex', ['apple', 'banana', 'cumquat']);
gui.add(s, 'byString', ['bird', 'cat', 'dog']);
gui.add(s, 'byKeyValue', [['Slow', 0.1], ['Medium', 0.5], ['Fast', 1.0]]);
gui.add(s, 'byKVArray', {keyValues: {'Loafers': 0, 'Sandals': 1, 'Sneakers': 2}});
Checkbox:
Sets a boolean
const s = {
on: true,
};
const gui = new GUI();
gui.add(s, 'on');
Colors:
Select a color in various formats
const s = {
byHashHex6: '#569AEF',
byHex6: 'EF569A',
byHashHex3: '#F88',
byHex3: '8F8',
byCSSRgb: 'rgb(170,68,240)',
byCSSHsl: 'hsl(170,100%,50%)',
byUint24: 0xFEA956,
byUint8: [255, 192, 255],
byUint8Array: new Uint8Array([75, 150, 225]),
byFloat32Array: new Float32Array([0.9, 0.7, 0.5]),
byNumberArray: [0.2, 0.9, 0.5],
byRGBObject: {r: 0, g: 0, b: 1},
byHashHex8: '#5438a180',
byUint32: 0xEF569A80,
byCSSRgba: 'rgba(64, 128, 255, 0.25)',
byCSSHslAlpha: 'hsl(180 100% 50% / 0.75)',
};
const gui = new GUI();
gui.addColor(s, 'byHashHex6');
gui.addColor(s, 'byHex6');
gui.addColor(s, 'byHashHex3');
gui.addColor(s, 'byHex3');
gui.addColor(s, 'byCSSRgb');
gui.addColor(s, 'byCSSHsl');
gui.addColor(s, 'byUint24', {format: 'uint32-rgb'});
gui.addColor(s, 'byUint8', {format: 'uint8-rgb'});
gui.addColor(s, 'byUint8Array');
gui.addColor(s, 'byFloat32Array');
gui.addColor(s, 'byNumberArray');
gui.addColor(s, 'byRGBObject');
gui.addLabel('with alpha');
gui.addColor(s, 'byHashHex8');
gui.addColor(s, 'byUint32', {format: 'uint32-rgba'});
gui.addColor(s, 'byCSSRgba');
gui.addColor(s, 'byCSSHslAlpha');
Canvas:
Lets you draw something
const waveData = new Array(100).fill(0);
const gui = new GUI();
helpers.graph(
gui.addCanvas('wave').canvas,
waveData,
{
min: -2,
max: +2,
interval: 200,
});
Returning just a canvas means you can use whatever API you want (2d, WebGL, WebGPU)
const hsl = (h, s, l) =>
`hsl(${h * 360 | 0}, ${s * 100}%, ${l * 100 | 0}%)`;
const gui = new GUI();
const canvas = gui.addCanvas('funky').canvas;
const ctx = canvas.getContext('2d');
function render(t) {
t *= 0.0001;
canvas.width = canvas.width;
ctx.translate(canvas.width / 2, canvas.height / 2);
const size = Math.max(canvas.width, canvas.height);
ctx.rotate(t);
for (let i = 0; i < 16; ++i) {
ctx.fillStyle = hsl(i / 48 + t * 0.2, 1, i % 2 ? 0.5 : 0.25);
ctx.fillRect(-size, -size, size * 2, size * 2);
ctx.scale(0.8, 0.8);
ctx.rotate(Math.sin(t * 3 + i * 0.1) * 0.2);
}
requestAnimationFrame(render);
}
requestAnimationFrame(render);
And you can use whatever Library (three.js, babylon.js, pixi.js) you want.
// three.js example
import {model} from '/examples/js/model.js';
const gui = new GUI();
const s = model(gui.addCanvas('model').canvas);
gui.addColor(s.material, 'color');
gui.add(s.material, 'shininess', 0, 300);
gui.addColor(s.light, 'color').name('light');
gui.add(s.light, 'intensity', 0, 5, 0.01);
gui.add(s.camera, 'fov', 1, 179);
Button:
Like <button type="button">
, calls a function
function doIt() { log('doIt'); }
function doThat() { log('doThat'); }
const s = {
clickMe() { log("clicked"); },
clickMeToo: () => { log("clicked too"); },
doIt,
doSomething: doThat,
};
const gui = new GUI();
gui.add(s, 'clickMe');
gui.add(s, 'clickMeToo');
gui.add(s, 'doIt');
gui.add(s, 'doSomething');
gui.addButton('easy', _ => log('e-z'));
Label:
Displays text. Can be used to label sections or to display info
const gui = new GUI();
gui.addLabel('Seconds:');
const output = gui.addLabel('');
setInterval(() => {
const secs = new Date().getSeconds();
const s = secs.toString().padStart(2, '0');
output.text(`---\n${s}\n---`);
}, 1000);
A small utility to monitor a value
const s = {
frameCount: 0,
stats: {
mode: 'searching',
speed: 12,
},
};
const gui = new GUI();
helpers.monitor(gui.addLabel('Seconds:'), s, 'frameCount');
helpers.monitor(gui.addLabel('Status:'), s, 'stats');
Text:
Like <input type="text">
, manipulates a string.
const s = {
name: "Sandy",
};
const gui = new GUI();
gui.add(s, 'name');
TextNumbers:
Like <input type="number">
, manipulates a number via text editing with optional conversions.
const s = {
value: 123,
angleDeg: 45,
angleRad: Math.PI,
};
const degToRad = d => d * Math.PI / 180;
const radToDeg = r => r * 180 / Math.PI;
const gui = new GUI();
gui.add(new TextNumber(s, 'value'));
gui.add(new TextNumber(s, 'angleRad', {
converters: {
to: radToDeg,
from: v => [true, degToRad(v)]},
step: 1,
}));
gui.add(new TextNumber(s, 'angleDeg', {
converters: {
to: degToRad,
from: v => [true, radToDeg(v)]},
step: 0.001,
}));
Listen:
Listens for changes.
const s = {
amount: 5,
name: 'Jim',
pet: 'cat',
randomize,
};
function randomize() {
s.amount = Math.random() * 50;
s.name = randElem(['Jane', 'Lee', 'Anne']);
s.pet = randElem(pets);
}
const pets = ['cat', 'dog', 'bird'];
const gui = new GUI();
gui.add(s, 'amount', 0, 50).listen();
gui.add(s, 'name').listen();
gui.add(s, 'pet', pets).listen();
gui.add(s, 'randomize');
updateDisplay:
Updates the UI from current value(s).
const s = {
amount: 5,
name: 'Jim',
pet: 'cat',
};
function randomize() {
s.amount = Math.random() * 50;
s.name = randElem(['Jane', 'Lee', 'Anne']);
s.pet = randElem(pets);
}
const pets = ['cat', 'dog', 'bird'];
const gui = new GUI();
const a = gui.add(s, 'amount', 0, 50);
const n = gui.add(s, 'name');
const p = gui.add(s, 'pet', pets);
gui.addButton('randomize', randomize);
gui.addButton('update amount', _ => a.updateDisplay());
gui.addButton('update name', _ => n.updateDisplay());
gui.addButton('update pet', _ => p.updateDisplay());
gui.addButton('update all', _ => gui.updateDisplay());
Folder:
A way to make collapsable sections.
const position = {
x: 5,
y: 20,
z: -15,
};
const rotation = {
x: 45,
y: 90,
z: -15,
};
const gui = new GUI();
const p = gui.addFolder('position');
p.add(position, 'x', -100, 100);
p.add(position, 'y', -100, 100);
p.add(position, 'z', -100, 100);
const r = gui.addFolder('rotation');
r.add(rotation, 'x', -100, 100);
r.add(rotation, 'y', -100, 100);
r.add(rotation, 'z', -100, 100);
Float Theme:
Useful when you want the UI over something
const gui = new GUI();
gui.setTheme('float');
gui.add(settings, 'period1', 0.1, 20);
gui.add(settings, 'period2', 0.1, 20);
gui.add(settings, 'p1', 0.1, 20);
gui.add(settings, 'p2', 0.1, 20);
gui.add(settings, 'heightMult', 1, 10);
gui.addColor(settings, 'baseColor');
Form Theme:
const s = {
name: "Jane Cheng",
address1: "B 1, No. 5, Xuzhou R",
address2: "Taipei 100218",
email: "jane_c@notreally.notcom",
receipt: true,
currency: '$',
};
const gui = new GUI();
gui.setTheme('form');
gui.add(s, 'name');
gui.add(s, 'address1');
gui.add(s, 'address2');
gui.add(s, 'email');
gui.add(s, 'receipt');
gui.add(
s, 'currency',
['$', '¥', '€', '£', '₣']);
gui.addButton('submit', submit);
//