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);








//
    
  
Fork me on GitHub