mirror of
https://github.com/SamEyeBam/animate.git
synced 2026-02-04 01:14:15 +00:00
rgb manipulation optimisation
This commit is contained in:
@@ -302,13 +302,24 @@ class ControlFactory {
|
||||
input.type = 'color';
|
||||
input.className = 'control control-color';
|
||||
input.id = `el${config.property}`;
|
||||
input.value = instance[config.property] ?? config.defaultValue;
|
||||
|
||||
// Handle both RGB array and hex string for initial value
|
||||
const currentValue = instance[config.property] ?? config.defaultValue;
|
||||
if (Array.isArray(currentValue)) {
|
||||
input.value = rgbArrayToHex(currentValue);
|
||||
} else {
|
||||
input.value = currentValue;
|
||||
// Also convert the instance value to RGB array if it's hex
|
||||
instance[config.property] = hexToRgbArray(currentValue);
|
||||
}
|
||||
|
||||
const listener = (event) => {
|
||||
const newValue = event.target.value;
|
||||
instance[config.property] = newValue;
|
||||
const hexValue = event.target.value;
|
||||
// Convert hex to RGB array for internal use
|
||||
const rgbValue = hexToRgbArray(hexValue);
|
||||
instance[config.property] = rgbValue;
|
||||
if (config.callback) {
|
||||
config.callback(instance, newValue);
|
||||
config.callback(instance, rgbValue);
|
||||
}
|
||||
};
|
||||
input.addEventListener('input', listener);
|
||||
|
||||
@@ -7,8 +7,8 @@ class CircleExpand extends BaseShape {
|
||||
{ type: 'range', min: 50, max: 150, defaultValue: 150, property: 'gap' },
|
||||
{ type: 'range', min: 0, max: 1, defaultValue: 1, property: 'linear' },
|
||||
{ type: 'range', min: 0, max: 1, defaultValue: 1, property: 'heart' },
|
||||
{ type: 'color', defaultValue: '#fc03cf', property: 'colour1' },
|
||||
{ type: 'color', defaultValue: '#00fffb', property: 'colour2' },
|
||||
{ type: 'color', defaultValue: [252, 3, 207], property: 'colour1' },
|
||||
{ type: 'color', defaultValue: [0, 255, 251], property: 'colour2' },
|
||||
];
|
||||
|
||||
constructor(nCircles, gap, linear, heart, colour1, colour2) {
|
||||
@@ -21,17 +21,6 @@ class CircleExpand extends BaseShape {
|
||||
this.colour2 = colour2;
|
||||
}
|
||||
|
||||
lerpColor(a, b, amount) {
|
||||
const ah = +a.replace('#', '0x');
|
||||
const ar = ah >> 16, ag = ah >> 8 & 0xff, ab = ah & 0xff;
|
||||
const bh = +b.replace('#', '0x');
|
||||
const br = bh >> 16, bg = bh >> 8 & 0xff, bb = bh & 0xff;
|
||||
const rr = ar + amount * (br - ar);
|
||||
const rg = ag + amount * (bg - ag);
|
||||
const rb = ab + amount * (bb - ab);
|
||||
return '#' + ((1 << 24) + (rr << 16) + (rg << 8) + rb | 0).toString(16).slice(1);
|
||||
}
|
||||
|
||||
arraySort(x, y) {
|
||||
if (x.r > y.r) return 1;
|
||||
if (x.r < y.r) return -1;
|
||||
@@ -80,7 +69,7 @@ class CircleExpand extends BaseShape {
|
||||
const newArr = arrOfWidths.sort(this.arraySort);
|
||||
|
||||
for (let i = this.nCircles - 1; i >= 0; i--) {
|
||||
const newColour = this.lerpColor(this.colour1, this.colour2, newArr[i].c);
|
||||
const newColour = colourToText(lerpRGB(this.colour1, this.colour2, newArr[i].c));
|
||||
|
||||
if (this.heart) {
|
||||
this.drawHeart(newArr[i].r, newColour);
|
||||
|
||||
@@ -48,7 +48,7 @@ class Countdown extends BaseShape {
|
||||
ctx.fillStyle = "white";
|
||||
ctx.textAlign = "center";
|
||||
|
||||
const futureDate = '2025-06-01T04:30:00';
|
||||
const futureDate = '2026-12-31T04:30:00';
|
||||
const seconds = this.secondsUntilDate(futureDate);
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const hours = Math.floor(seconds / 3600);
|
||||
|
||||
@@ -15,9 +15,9 @@ class EyePrototype extends BaseShape {
|
||||
{ type: 'range', min: 0, max: 1, defaultValue: 0, property: 'draw_expand' },
|
||||
{ type: 'range', min: 0, max: 1, defaultValue: 1, property: 'draw_hypno' },
|
||||
{ type: 'range', min: 1, max: 10, defaultValue: 1, property: 'line_width' },
|
||||
{ type: 'color', defaultValue: '#00fffb', property: 'colourPupil' },
|
||||
{ type: 'color', defaultValue: '#ff0000', property: 'colourSpiral' },
|
||||
{ type: 'color', defaultValue: '#00fffb', property: 'colourExpand' },
|
||||
{ type: 'color', defaultValue: [0, 255, 251], property: 'colourPupil' },
|
||||
{ type: 'color', defaultValue: [255, 0, 0], property: 'colourSpiral' },
|
||||
{ type: 'color', defaultValue: [0, 255, 251], property: 'colourExpand' },
|
||||
{ type: 'range', min: 0, max: 1, defaultValue: 1, property: 'draw_eyelid' },
|
||||
];
|
||||
|
||||
@@ -42,7 +42,7 @@ class EyePrototype extends BaseShape {
|
||||
this.colourPupil = colourPupil;
|
||||
this.colourSpiral = colourSpiral;
|
||||
this.colourExpand = colourExpand;
|
||||
this.centerPulse = new CircleExpand(10, 30, 1, 0, "#2D81FC", "#FC0362");
|
||||
this.centerPulse = new CircleExpand(10, 30, 1, 0, [45, 129, 252], [252, 3, 98]);
|
||||
}
|
||||
|
||||
drawEyelid(rotation) {
|
||||
@@ -94,7 +94,7 @@ class EyePrototype extends BaseShape {
|
||||
}
|
||||
|
||||
drawGrowEye(step) {
|
||||
ctx.strokeStyle = this.colourExpand;
|
||||
ctx.strokeStyle = colourToText(this.colourExpand);
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 5;
|
||||
ctx.arc(centerX + this.x, centerY + this.y, step, 0, 2 * Math.PI);
|
||||
@@ -102,7 +102,7 @@ class EyePrototype extends BaseShape {
|
||||
}
|
||||
|
||||
drawCircle(step) {
|
||||
ctx.strokeStyle = this.colourPupil;
|
||||
ctx.strokeStyle = colourToText(this.colourPupil);
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 5;
|
||||
ctx.arc(centerX + this.x, centerY + this.y, step, 0, 2 * Math.PI);
|
||||
@@ -110,7 +110,7 @@ class EyePrototype extends BaseShape {
|
||||
}
|
||||
|
||||
drawSpiral(step) {
|
||||
ctx.strokeStyle = this.colourSpiral;
|
||||
ctx.strokeStyle = colourToText(this.colourSpiral);
|
||||
const a = 1;
|
||||
const b = 5;
|
||||
ctx.moveTo(centerX, centerY);
|
||||
|
||||
@@ -5,7 +5,7 @@ class FloralAccident extends BaseShape {
|
||||
static config = [
|
||||
{ type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' },
|
||||
{ type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' },
|
||||
{ type: 'color', defaultValue: '#4287f5', property: 'colour' },
|
||||
{ type: 'color', defaultValue: [66, 135, 245], property: 'colour' },
|
||||
];
|
||||
|
||||
constructor(sides, width, colour) {
|
||||
@@ -36,7 +36,7 @@ class FloralAccident extends BaseShape {
|
||||
end + rad(n),
|
||||
0
|
||||
);
|
||||
ctx.strokeStyle = this.colour;
|
||||
ctx.strokeStyle = colourToText(this.colour);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.beginPath();
|
||||
@@ -48,7 +48,7 @@ class FloralAccident extends BaseShape {
|
||||
end - (end - stt - rad(rotation)) / 2 + rad(n),
|
||||
0
|
||||
);
|
||||
ctx.strokeStyle = this.colour;
|
||||
ctx.strokeStyle = colourToText(this.colour);
|
||||
ctx.stroke();
|
||||
|
||||
stt = end + -(rad(rot - piv));
|
||||
|
||||
@@ -6,8 +6,8 @@ class FloralPhyllo extends BaseShape {
|
||||
{ type: 'range', min: 1, max: 600, defaultValue: 300, property: 'width' },
|
||||
{ type: 'range', min: 1, max: 300, defaultValue: 150, property: 'depth' },
|
||||
{ type: 'range', min: 0, max: 3141, defaultValue: 0, property: 'start' },
|
||||
{ type: 'color', defaultValue: '#4287f5', property: 'colour1' },
|
||||
{ type: 'color', defaultValue: '#FC0362', property: 'colour2' },
|
||||
{ type: 'color', defaultValue: [66, 135, 245], property: 'colour1' },
|
||||
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
||||
];
|
||||
|
||||
constructor(width, depth, start, colour1, colour2) {
|
||||
@@ -26,7 +26,7 @@ class FloralPhyllo extends BaseShape {
|
||||
const c = 1;
|
||||
|
||||
for (let n = this.depth; n > 0; n -= 1) {
|
||||
const ncolour = LerpHex(this.colour1, this.colour2, n / this.depth);
|
||||
const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, n / this.depth));
|
||||
const a = n * rotation / 1000;
|
||||
const r = c * Math.sqrt(n);
|
||||
const x = r * Math.cos(a) + centerX;
|
||||
|
||||
@@ -5,8 +5,8 @@ class FloralPhyllo_Accident extends BaseShape {
|
||||
static config = [
|
||||
{ type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' },
|
||||
{ type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' },
|
||||
{ type: 'color', defaultValue: '#2D81FC', property: 'colour1' },
|
||||
{ type: 'color', defaultValue: '#FC0362', property: 'colour2' },
|
||||
{ type: 'color', defaultValue: [45, 129, 252], property: 'colour1' },
|
||||
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
||||
];
|
||||
|
||||
constructor(sides, width, colour1, colour2) {
|
||||
@@ -23,7 +23,7 @@ class FloralPhyllo_Accident extends BaseShape {
|
||||
const c = 24;
|
||||
|
||||
for (let n = 0; n < 300; n += 1) {
|
||||
const ncolour = LerpHex(this.colour1, this.colour2, Math.cos(rad(n / 2)));
|
||||
const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, Math.cos(rad(n / 2))));
|
||||
const a = n * (rotation / 1000 + 100);
|
||||
const r = c * Math.sqrt(n);
|
||||
const x = r * Math.cos(a) + centerX;
|
||||
|
||||
@@ -23,9 +23,9 @@ class MaryFace extends BaseShape {
|
||||
this.y2 = y2;
|
||||
this.rotate2 = rotate2;
|
||||
this.width2 = width2;
|
||||
this.eye1 = new EyePrototype(x1, y1, rotate1, 0, width1, 10, 1, 1, 0, 0, 0, 1, "#00fffb", "#00fffb", "#00fffb");
|
||||
this.eye2 = new EyePrototype(x2, y2, rotate2, 0, width2, 10, 1, 1, 0, 0, 0, 1, "#00fffb", "#00fffb", "#00fffb");
|
||||
this.eye3 = new EyePrototype(110, -280, rotate2 + 2, 1, width2, 10, 1, 1, 0, 0, 0, 1, "#00fffb", "#00fffb", "#00fffb");
|
||||
this.eye1 = new EyePrototype(x1, y1, rotate1, 0, width1, 10, 1, 1, 0, 0, 0, 1, [0, 255, 251], [0, 255, 251], [0, 255, 251]);
|
||||
this.eye2 = new EyePrototype(x2, y2, rotate2, 0, width2, 10, 1, 1, 0, 0, 0, 1, [0, 255, 251], [0, 255, 251], [0, 255, 251]);
|
||||
this.eye3 = new EyePrototype(110, -280, rotate2 + 2, 1, width2, 10, 1, 1, 0, 0, 0, 1, [0, 255, 251], [0, 255, 251], [0, 255, 251]);
|
||||
}
|
||||
|
||||
draw(elapsed) {
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
*/
|
||||
class Nodal_expanding extends BaseShape {
|
||||
static config = [
|
||||
{ type: 'range', min: 1, max: 100, defaultValue: 5, property: 'expand' },
|
||||
{ type: 'range', min: 0, max: 100, defaultValue: 0.1, property: 'expand' },
|
||||
{ type: 'range', min: 1, max: 1000, defaultValue: 150, property: 'points' },
|
||||
{ type: 'range', min: 1, max: 360, defaultValue: 0, property: 'start' },
|
||||
{ type: 'range', min: 1, max: 10, defaultValue: 6, property: 'line_width' },
|
||||
{ type: 'color', defaultValue: '#2D81FC', property: 'colour1' },
|
||||
{ type: 'color', defaultValue: '#FC0362', property: 'colour2' },
|
||||
{ type: 'color', defaultValue: [45, 129, 252], property: 'colour1' },
|
||||
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
||||
{ type: 'range', min: 0, max: 10, defaultValue: 5, property: 'colour_change' },
|
||||
];
|
||||
|
||||
@@ -31,7 +31,7 @@ class Nodal_expanding extends BaseShape {
|
||||
|
||||
for (let z = 1; z <= this.points; z++) {
|
||||
ctx.beginPath();
|
||||
const ncolour = LerpHex(this.colour1, this.colour2, z / this.points);
|
||||
const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, z / this.points));
|
||||
|
||||
ctx.moveTo(
|
||||
centerX + (Math.cos(rad(angle * (z - 1) + 0)) * (length - this.expand)),
|
||||
|
||||
@@ -9,8 +9,8 @@ class PhylloCone extends BaseShape {
|
||||
{ type: 'range', min: 1, max: 2000, defaultValue: 1000, property: 'iterations' },
|
||||
{ type: 'range', min: 1, max: 10, defaultValue: 2, property: 'distance' },
|
||||
{ type: 'range', min: 1, max: 10, defaultValue: 2, property: 'line_width' },
|
||||
{ type: 'color', defaultValue: '#2D81FC', property: 'colour1' },
|
||||
{ type: 'color', defaultValue: '#FC0362', property: 'colour2' },
|
||||
{ type: 'color', defaultValue: [45, 129, 252], property: 'colour1' },
|
||||
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
||||
|
||||
];
|
||||
|
||||
@@ -43,7 +43,7 @@ class PhylloCone extends BaseShape {
|
||||
ctx.lineTo(xCoord, yCoord);
|
||||
}
|
||||
ctx.lineWidth = this.line_width;
|
||||
ctx.strokeStyle = this.colour1;
|
||||
ctx.strokeStyle = colourToText(this.colour1);
|
||||
ctx.stroke();
|
||||
console.log(this.line_width);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ class Phyllotaxis extends BaseShape {
|
||||
{ type: 'range', min: 0, max: 3141, defaultValue: 0, property: 'start' },
|
||||
{ type: 'range', min: 1, max: 10000, defaultValue: 300, property: 'nMax' },
|
||||
{ type: 'checkbox', defaultValue: false, property: 'giggle' },
|
||||
{ type: 'color', defaultValue: '#2D81FC', property: 'colour1' },
|
||||
{ type: 'color', defaultValue: '#FC0362', property: 'colour2' },
|
||||
{ type: 'color', defaultValue: [45, 129, 252], property: 'colour1' },
|
||||
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
||||
];
|
||||
|
||||
constructor(width, size, sizeMin, start, nMax, giggle, colour1, colour2) {
|
||||
@@ -32,7 +32,7 @@ class Phyllotaxis extends BaseShape {
|
||||
|
||||
for (let n = 0; n < maxIterations; n++) {
|
||||
ctx.beginPath();
|
||||
const ncolour = LerpHex(this.colour1, this.colour2, n / this.nMax);
|
||||
const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, n / this.nMax));
|
||||
const nAngle = n * angle + Math.sin(rad(n * 1 + angle * 40000)) / 2;
|
||||
const radius = distanceMultiplier * n;
|
||||
const xCoord = radius * Math.cos(nAngle) + centerX;
|
||||
@@ -52,7 +52,7 @@ class Phyllotaxis extends BaseShape {
|
||||
this.drawGiggle(rotation);
|
||||
} else {
|
||||
for (let n = 0; n < this.nMax; n += 1) {
|
||||
const ncolour = LerpHex(this.colour1, this.colour2, n / this.nMax);
|
||||
const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, n / this.nMax));
|
||||
const a = n * (rotation / 1000);
|
||||
const r = this.width * Math.sqrt(n);
|
||||
const x = r * Math.cos(a) + centerX;
|
||||
|
||||
@@ -8,8 +8,8 @@ class PolyTwistColourWidth extends BaseShape {
|
||||
{ type: 'range', min: 2, max: 5, defaultValue: 5, property: 'line_width' },
|
||||
{ type: 'range', min: 1, max: 100, defaultValue: 50, property: 'depth' },
|
||||
{ type: 'range', min: -180, max: 180, defaultValue: -90, property: 'rotation' },
|
||||
{ type: 'color', defaultValue: '#4287f5', property: 'colour1' },
|
||||
{ type: 'color', defaultValue: '#42f57b', property: 'colour2' },
|
||||
{ type: 'color', defaultValue: [66, 135, 245], property: 'colour1' },
|
||||
{ type: 'color', defaultValue: [66, 245, 123], property: 'colour2' },
|
||||
];
|
||||
|
||||
constructor(sides, width, line_width, depth, rotation, colour1, colour2) {
|
||||
@@ -41,7 +41,7 @@ class PolyTwistColourWidth extends BaseShape {
|
||||
|
||||
for (let i = 0; i < this.depth; i++) {
|
||||
const fraction = i / this.depth;
|
||||
const ncolour = LerpHex(this.colour1, this.colour2, fraction);
|
||||
const ncolour = colourToText(lerpRGB(this.colour1, this.colour2, fraction));
|
||||
DrawPolygon(this.sides, this.width * widthMultiplier ** i, out_angle * i + this.rotation, ncolour, this.line_width);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ class RaysInShape extends BaseShape {
|
||||
{ type: 'range', min: 1, max: 80, defaultValue: 5, property: 'trailLength' },
|
||||
{ type: 'range', min: 1, max: 500, defaultValue: 5, property: 'lineWidth' },
|
||||
{ type: 'checkbox', defaultValue: false, property: 'fade' },
|
||||
{ type: 'color', defaultValue: '#43dbad', property: 'colourFree' },
|
||||
{ type: 'color', defaultValue: '#f05c79', property: 'colourContained' },
|
||||
{ type: 'color', defaultValue: [67, 219, 173], property: 'colourFree' },
|
||||
{ type: 'color', defaultValue: [240, 92, 121], property: 'colourContained' },
|
||||
{ type: 'header', text: '--CollisionBox---' },
|
||||
{ type: 'checkbox', defaultValue: false, property: 'boxVisible' },
|
||||
];
|
||||
@@ -134,8 +134,8 @@ class RaysInShape extends BaseShape {
|
||||
ctx.moveTo(prev.x, prev.y);
|
||||
ctx.lineTo(curr.x, curr.y);
|
||||
|
||||
const col = hexToRgb(this.colourFree);
|
||||
ctx.strokeStyle = `rgba(${col.r}, ${col.g}, ${col.b}, ${alpha})`;
|
||||
const col = this.colourFree;
|
||||
ctx.strokeStyle = `rgba(${col[0]}, ${col[1]}, ${col[2]}, ${alpha})`;
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
@@ -274,8 +274,8 @@ class RaysInShape extends BaseShape {
|
||||
if (curr.collision) {
|
||||
ctx.strokeStyle = `rgba(255, 255, 0, ${alpha})`;
|
||||
} else {
|
||||
const col = hexToRgb(this.colourContained);
|
||||
ctx.strokeStyle = `rgba(${col.r}, ${col.g}, ${col.b}, ${alpha})`;
|
||||
const col = this.colourContained;
|
||||
ctx.strokeStyle = `rgba(${col[0]}, ${col[1]}, ${col[2]}, ${alpha})`;
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
@@ -5,7 +5,7 @@ class Spiral1 extends BaseShape {
|
||||
static config = [
|
||||
{ type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' },
|
||||
{ type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' },
|
||||
{ type: 'color', defaultValue: '#4287f5', property: 'colour' },
|
||||
{ type: 'color', defaultValue: [66, 135, 245], property: 'colour' },
|
||||
];
|
||||
|
||||
constructor(sides, width, colour) {
|
||||
@@ -37,7 +37,7 @@ class Spiral1 extends BaseShape {
|
||||
end + rad(rotation) + rad(n),
|
||||
0
|
||||
);
|
||||
ctx.strokeStyle = this.colour;
|
||||
ctx.strokeStyle = colourToText(this.colour);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.beginPath();
|
||||
@@ -49,7 +49,7 @@ class Spiral1 extends BaseShape {
|
||||
end - (end - stt) / 2 + rad(n) - rad(rotation),
|
||||
0
|
||||
);
|
||||
ctx.strokeStyle = this.colour;
|
||||
ctx.strokeStyle = colourToText(this.colour);
|
||||
ctx.stroke();
|
||||
|
||||
stt = end + -(rad(rot - piv));
|
||||
|
||||
@@ -5,7 +5,7 @@ class SquareTwist_angle extends BaseShape {
|
||||
static config = [
|
||||
{ type: 'range', min: 1, max: 800, defaultValue: 400, property: 'width' },
|
||||
{ type: 'range', min: 1, max: 10, defaultValue: 1, property: 'line_width' },
|
||||
{ type: 'color', defaultValue: '#2D81FC', property: 'colour1' },
|
||||
{ type: 'color', defaultValue: [45, 129, 252], property: 'colour1' },
|
||||
];
|
||||
|
||||
constructor(width, line_width, colour1) {
|
||||
@@ -20,7 +20,7 @@ class SquareTwist_angle extends BaseShape {
|
||||
ctx.translate(centerX, centerY);
|
||||
ctx.rotate(rad(angle + 180));
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = colour;
|
||||
ctx.strokeStyle = colourToText(colour);
|
||||
ctx.lineWidth = this.line_width;
|
||||
ctx.rect(-size / 2, -size / 2, size, size);
|
||||
ctx.stroke();
|
||||
|
||||
@@ -21,18 +21,36 @@ function colourToText(colour) {
|
||||
return "rgb(" + colour[0] + "," + colour[1] + "," + colour[2] + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert hex color to RGB object
|
||||
* @param {string} hex - Hex color string (e.g., '#ff0000')
|
||||
* @returns {{r: number, g: number, b: number}|null} RGB object or null
|
||||
* Convert hex color to RGB array
|
||||
* @param {string} hex - Hex color string (with or without #)
|
||||
* @returns {number[]} RGB array [r, g, b]
|
||||
*/
|
||||
function hexToRgbArray(hex) {
|
||||
// supports "#RRGGBB" (you can add "#RGB" if needed)
|
||||
if (hex[0] === "#") hex = hex.slice(1);
|
||||
const n = parseInt(hex, 16);
|
||||
return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hex color to RGB object (for backward compatibility)
|
||||
* @param {string} hex - Hex color string (with or without #)
|
||||
* @returns {{r: number, g: number, b: number}} RGB object
|
||||
*/
|
||||
function hexToRgb(hex) {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result ? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16)
|
||||
} : null;
|
||||
const arr = hexToRgbArray(hex);
|
||||
return { r: arr[0], g: arr[1], b: arr[2] };
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RGB array to hex color string
|
||||
* @param {number[]} rgb - RGB array [r, g, b]
|
||||
* @returns {string} Hex color string with #
|
||||
*/
|
||||
function rgbArrayToHex(rgb) {
|
||||
return "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,23 +91,6 @@ function lerpRGB(a, b, t) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy LerpRGB function (handles negative t)
|
||||
* @param {number[]} a - Start RGB array
|
||||
* @param {number[]} b - End RGB array
|
||||
* @param {number} t - Interpolation amount
|
||||
* @returns {number[]} Interpolated RGB array
|
||||
*/
|
||||
function LerpRGB(a, b, t) {
|
||||
if (t < 0) {
|
||||
t *= -1;
|
||||
}
|
||||
const newColor = [0, 0, 0];
|
||||
newColor[0] = a[0] + (b[0] - a[0]) * t;
|
||||
newColor[1] = a[1] + (b[1] - a[1]) * t;
|
||||
newColor[2] = a[2] + (b[2] - a[2]) * t;
|
||||
return newColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a wave-normalized value (0-1 range using sine)
|
||||
|
||||
Reference in New Issue
Block a user