Tengo una lista de colores y me gustaría tener un método que, dada una lista de colores, pueda interpolarlos linealmente con paradas distribuidas uniformemente por color, por ejemplo, si hay cuatro colores: el color uno a dos sería interpola de 0 a 0,25, colorea de dos a tres de 0,25 a 0,5 y así sucesivamente.
En mi ejemplo rudimentario, actualmente estoy usando una aproximación del valor del seno para activar el siguiente color en la matriz, pero como es de esperar, se llama al índice más de una vez, lo que hace que se salten colores. Además, no puedo encontrar la fórmula que me permita distribuir los valores de los colores de manera uniforme para poder hacer la transición de todos a la vez desde el valor normalizado del ciclo.
Sé que CSS puede cambiar fácilmente los colores y hay bibliotecas que pueden hacer cosas similares, pero me gustaría saber las matemáticas para hacer esto e implementarlas en Javascript usando la API de Canvas sin bibliotecas de terceros.
const rgbColors = [ [255, 0, 0], [0, 255, 0], [255, 0, 0], [0, 255, 255] ]; const canvas = document.querySelector("canvas"); const ctx = canvas.getContext("2d"); const lerp = (x, y, a) => x * (1 - a) + y * a; let start = performance.now(); let currentIndex = 0; function getColorLERP(colorA, colorB, progress) { const r = Math.round(lerp(colorA[0], colorB[0], progress) * 10) / 10; const g = Math.round(lerp(colorA[1], colorB[1], progress) * 10) / 10; const b = Math.round(lerp(colorA[2], colorB[2], progress) * 10) / 10; return [r, g, b]; } const loop = (now) => { window.requestAnimationFrame(loop); const delta = Math.round(now - start); const yoyoRate = delta * 0.0005; const yoyo = Math.abs(Math.sin(yoyoRate)); const [r, g, b] = getColorLERP( rgbColors[currentIndex], rgbColors[(currentIndex + 1) % rgbColors.length], yoyo ); ctx.fillStyle = `rgb(${r}, ${g}, ${b})`; ctx.fillRect(0, 0, 200, 200); ctx.fillStyle = "#000"; if (yoyo > 0.9999) { currentIndex++; if (currentIndex > rgbColors.length - 1) { currentIndex = 0; } } }; loop(); <canvas width=200 height=200></canvas>Simplemente usaría CSS para hacer los cálculos por mí. No mencionaste ninguna restricción en las tecnologías...
const colors = ['red', 'green', 'red', 'cyan']; let colorIndex = 0; setInterval(() => { document.querySelector('.box').classList.remove(colors[colorIndex++ % 4]); document.querySelector('.box').classList.add(colors[colorIndex % 4]); }, 1000); .red { background-color: rgb(255,0,0); } .green { background-color: rgb(0,255,0); } .cyan { background-color: rgb(0,255,255); } .box { transition: background-color 1000ms linear; width: 200px; height: 200px; } <div class="box red"></div>