textmode.js / TextmodeColor
Class: TextmodeColor
Color value used by textmode drawing APIs.
Values are stored as 0-255 integers for compatibility with public APIs. Normalized versions are also available for shader uploads.
Use Textmodifier.color to create colors.
Example
const t = textmode.create({
width: window.innerWidth,
height: window.innerHeight,
fontSize: 16,
});
const labelLayer = t.layers.add();
t.draw(() => {
t.background(6, 10, 22);
});
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
const col1 = t.color(255, 120, 80);
const col2 = t.color('#80FFB0');
const col3 = t.color(180);
drawText('TEXTMODECOLOR.CREATION', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: STATIC COLOR CREATOR', x, y++, 100, 220, 255);
drawText('Supports RGB, Hex strings, Grays.', x, y++, 140, 160, 190);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('RGB : 255, 120, 80', x, y++, col1.r, col1.g, col1.b);
drawText('Hex : #80FFB0', x, y++, col2.r, col2.g, col2.b);
drawText('Gray: 180', x, y++, col3.r, col3.g, col3.b);
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});Properties
a
readonly a: number;Alpha component (0-255).
Example
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight });
const labelLayer = t.layers.add();
let currentAlpha = 255;
t.draw(() => {
t.background(0);
const time = t.frameCount * 0.05;
const trailLen = 15;
for (let i = 0; i < trailLen; i++) {
const alpha = 255 * (1 - i / trailLen);
const col = t.color(255, 255, 255, alpha);
const tOffset = time - i * 0.1;
const x = Math.cos(tOffset) * 15;
const y = Math.sin(tOffset) * 15;
t.push();
t.translate(x, y);
t.char(col.a > 128 ? '@' : '.');
t.charColor(col);
t.point();
t.pop();
}
const activeColor = t.color(255, 255, 255, 128 + Math.round(127 * Math.sin(time)));
currentAlpha = activeColor.a;
});
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
drawText('TEXTMODECOLOR.A', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: ALPHA COLOR CHANNEL READ', x, y++, 100, 220, 255);
drawText('Accesses alpha opacity of active color.', x, y++, 140, 160, 190);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText(`ALPHA VALUE : ${currentAlpha}`, x, y++, 240, 240, 240);
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});b
readonly b: number;Blue component (0-255).
Example
const t = textmode.create({
width: window.innerWidth,
height: window.innerHeight,
fontSize: 16,
});
const labelLayer = t.layers.add();
let centerBlue = 0;
t.draw(() => {
t.background(6, 10, 22);
const time = t.frameCount * 0.02;
for (let y = -6; y <= 6; y++) {
const phase = y * 0.3 + time;
const shapedWave = 0.7 * Math.sin(phase) + 0.3 * Math.sin(phase * 3);
const blue = Math.round(50 + shapedWave * 180);
const c = t.color(80, 120, blue);
const offset = shapedWave * 3;
t.push();
t.translate(offset, y);
t.charColor(c.r, c.g, c.b);
t.char('~');
t.rect(Math.abs(shapedWave) * 12 + 2, 1);
t.pop();
}
centerBlue = Math.round(50 + Math.abs(Math.sin(time)) * 180);
});
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
drawText('TEXTMODECOLOR.B', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: BLUE COLOR CHANNEL READ', x, y++, 100, 220, 255);
drawText('Accesses blue channel of active color.', x, y++, 140, 160, 190);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText(`BLUE VALUE : ${centerBlue}`, x, y++, 80, 120, centerBlue);
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});g
readonly g: number;Green component (0-255).
Example
const t = textmode.create({
width: window.innerWidth,
height: window.innerHeight,
fontSize: 16,
});
const labelLayer = t.layers.add();
let centerGreen = 0;
t.draw(() => {
t.background(6, 10, 22);
const time = t.frameCount * 0.02;
for (let y = -6; y <= 6; y++) {
const phase = y * 0.3 + time;
const shapedWave = 0.7 * Math.sin(phase) + 0.3 * Math.sin(phase * 3);
const green = Math.round(50 + shapedWave * 180);
const c = t.color(80, green, 120);
const offset = shapedWave * 3;
t.push();
t.translate(offset, y);
t.charColor(c.r, c.g, c.b);
t.char('~');
t.rect(Math.abs(shapedWave) * 12 + 2, 1);
t.pop();
}
centerGreen = Math.round(50 + Math.abs(Math.sin(time)) * 180);
});
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
drawText('TEXTMODECOLOR.G', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: GREEN COLOR CHANNEL READ', x, y++, 100, 220, 255);
drawText('Accesses green channel of active color.', x, y++, 140, 160, 190);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText(`GREEN VALUE : ${centerGreen}`, x, y++, 80, centerGreen, 120);
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});r
readonly r: number;Red component (0-255).
Example
const t = textmode.create({
width: window.innerWidth,
height: window.innerHeight,
fontSize: 16,
});
const labelLayer = t.layers.add();
let centerRed = 0;
t.draw(() => {
t.background(6, 10, 22);
const time = t.frameCount * 0.02;
for (let y = -6; y <= 6; y++) {
const phase = y * 0.3 + time;
const shapedWave = 0.7 * Math.sin(phase) + 0.3 * Math.sin(phase * 3);
const red = Math.round(80 + shapedWave * 175);
const c = t.color(red, 40, 40);
const offset = shapedWave * 3;
t.push();
t.translate(offset, y);
t.charColor(c.r, c.g, c.b);
t.char('~');
t.rect(Math.abs(shapedWave) * 12 + 2, 1);
t.pop();
}
centerRed = Math.round(80 + Math.abs(Math.sin(time)) * 175);
});
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
drawText('TEXTMODECOLOR.R', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: RED COLOR CHANNEL READ', x, y++, 100, 220, 255);
drawText('Accesses red channel of active color.', x, y++, 140, 160, 190);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText(`RED VALUE : ${centerRed}`, x, y++, centerRed, 40, 40);
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});Accessors
normalized
Get Signature
get normalized(): [number, number, number, number];Normalized (0-1) RGBA tuple.
Useful for passing color data to WebGL shaders.
Returns
[number, number, number, number]
A [r, g, b, a] tuple where each component is between 0.0 and 1.0.
Example
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight });
const labelLayer = t.layers.add();
const color = t.color(255, 128, 0, 255);
const labels = ['R', 'G', 'B', 'A'];
const colors = [
[255, 100, 100],
[120, 255, 140],
[120, 180, 255],
[240, 240, 240],
];
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
function drawMeter(label, value, y, rgb, phase, x) {
const blocks = Math.round(value * 10);
drawText(`${label} ${value.toFixed(2)}`, x, y, rgb[0], rgb[1], rgb[2]);
for (let i = 0; i < 10; i++) {
const active = i < blocks;
const glow = active ? 40 + Math.round(60 * (0.5 + 0.5 * Math.sin(t.frameCount * 0.12 + phase + i))) : 0;
const meterColor = active
? [Math.min(255, rgb[0] + glow), Math.min(255, rgb[1] + glow), Math.min(255, rgb[2] + glow)]
: [55, 65, 80];
t.push();
t.translate(x + 13 + i, y);
t.charColor(meterColor[0], meterColor[1], meterColor[2]);
t.char(active ? '|' : '.');
t.point();
t.pop();
}
}
t.draw(() => {
t.background(12, 16, 24);
});
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
const normalized = color.normalized;
const rgba = color.rgba.join(', ');
drawText('TEXTMODECOLOR.NORMALIZED', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: NORMALIZED FLOAT VALUES', x, y++, 100, 220, 255);
drawText(`RGBA : [${rgba}]`, x, y++, color.rgb[0], color.rgb[1], color.rgb[2]);
drawText('------------------------------------', x, y++, 80, 100, 150);
for (let i = 0; i < labels.length; i++) {
drawMeter(labels[i], normalized[i], y++, colors[i], i * 0.8, x);
}
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});rgb
Get Signature
get rgb(): [number, number, number];Plain RGB tuple with integer components.
Returns
[number, number, number]
A [r, g, b] tuple with values between 0 and 255.
Example
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight });
const labelLayer = t.layers.add();
const color = t.color(50, 100, 200);
const labels = ['R', 'G', 'B'];
const channelColors = [
[255, 110, 110],
[120, 255, 140],
[120, 180, 255],
];
t.draw(() => {
const [r, g, b] = color.rgb;
const values = [r, g, b];
t.background(10, 14, 24);
for (let i = 0; i < values.length; i++) {
const angle = t.frameCount * 0.03 + (Math.PI * 2 * i) / values.length;
const radius = 6 + (values[i] / 255) * 8;
const x = Math.round(Math.cos(angle) * radius * 1.4);
const y = Math.round(Math.sin(angle) * radius);
t.push();
t.translate(x, y);
t.charColor(channelColors[i][0], channelColors[i][1], channelColors[i][2]);
t.char(labels[i]);
t.point();
t.pop();
}
t.push();
t.charColor(color);
t.char('o');
t.rect(8, 4);
t.pop();
});
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
const [r, g, b] = color.rgb;
drawText('TEXTMODECOLOR.RGB', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: RGB COLOR COMPONENTS', x, y++, 100, 220, 255);
drawText('Accesses red, green, blue channels.', x, y++, 140, 160, 190);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText(`RGB ARRAY : [${r}, ${g}, ${b}]`, x, y++, color.rgb[0], color.rgb[1], color.rgb[2]);
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});rgba
Get Signature
get rgba(): [number, number, number, number];Plain RGBA tuple with integer components.
Returns
[number, number, number, number]
A [r, g, b, a] tuple with values between 0 and 255.
Example
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight });
const labelLayer = t.layers.add();
const color = t.color(255, 128, 0, 100);
function drawChecker(x, y, width, height) {
for (let row = 0; row < height; row++) {
for (let col = 0; col < width; col++) {
if ((row + col) % 2 !== 0) {
continue;
}
t.push();
t.translate(x + col, y + row);
t.charColor(90, 100, 120, 90);
t.char('.');
t.point();
t.pop();
}
}
}
function drawSwatch(x, swatchColor, alpha = 255) {
const left = x - 4;
drawChecker(left, -2, 8, 4);
t.push();
t.translate(x, 0);
t.charColor(swatchColor[0], swatchColor[1], swatchColor[2], alpha);
t.char('@');
t.rect(8, 4);
t.pop();
}
t.draw(() => {
const [r, g, b, a] = color.rgba;
const offset = Math.min(11, Math.max(8, Math.floor(t.grid.cols / 4)));
t.background(12, 16, 24);
drawSwatch(-offset, [r, g, b], 255);
drawSwatch(offset, [r, g, b], a);
});
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
const [r, g, b, a] = color.rgba;
drawText('TEXTMODECOLOR.RGBA', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: RGBA COLOR SPECIFICATION', x, y++, 100, 220, 255);
drawText(`COLOR ARY : [${r}, ${g}, ${b}, ${a}]`, x, y++, 140, 160, 190);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('Left Swatch : Alpha = 255', x, y++, 140, 190, 255);
drawText(`Right Swatch: Alpha = ${a}`, x, y++, 140, 190, 255);
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});Methods
withAlpha()
withAlpha(alpha): TextmodeColor;Create a copy of this color with a different alpha value.
Useful for creating semi-transparent variations of existing colors without manually copying RGB components.
Parameters
| Parameter | Type | Description |
|---|---|---|
alpha | number | The new alpha value (0-255). Values outside this range will be clamped. |
Returns
TextmodeColor
A new TextmodeColor instance with the updated alpha.
Example
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight });
const layers = Array.from({ length: 5 }, () => t.layers.add());
const labelLayer = t.layers.add();
t.draw(() => {
t.background(0);
});
layers.forEach((layer, i) => {
layer.draw(() => {
t.clear();
const base = t.color(50, 150, 255);
const opacity = 100 + i * 30;
t.push();
t.translate((i - 2) * 5, Math.sin(t.frameCount * 0.05 + i) * 5);
t.charColor(base.withAlpha(opacity));
t.char(String.fromCharCode(65 + i));
t.rect(12, 12);
t.pop();
});
});
function drawText(text, x, y, r = 220, g = 230, b = 255) {
t.push();
t.translate(x, y);
t.charColor(r, g, b);
for (let i = 0; i < text.length; i++) {
t.char(text[i]);
t.point();
t.translate(1, 0);
}
t.pop();
}
labelLayer.draw(() => {
t.clear();
const left = -Math.floor(t.grid.cols / 2);
const top = -Math.floor(t.grid.rows / 2);
let y = top + 3;
const x = left + 3;
drawText('TEXTMODECOLOR.WITHALPHA', x, y++, 100, 255, 140);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('CONCEPT: CLONE COLOR WITH NEW ALPHA', x, y++, 100, 220, 255);
drawText('Returns copy with adjusted opacity.', x, y++, 140, 160, 190);
drawText('------------------------------------', x, y++, 80, 100, 150);
drawText('Rendering layers A-E with alpha.', x, y++, 140, 190, 255);
});
t.windowResized(() => {
t.resizeCanvas(window.innerWidth, window.innerHeight);
});