JavaScript 画布 - 平滑变换 RGB

3

我想把一个矩形的颜色从“黄色”改为“蓝色”。我使用fillStyle和rgb来实现。

var 
    canvas = document.getElementById('mycanvas'),
    ctx = document.getElementById('mycanvas').getContext('2d'),
    red = 255,
    blue = 0,
    green = 179,
    inc = 2;

function animate(){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.beginPath();
    ctx.rect(100, 100, 100, 100);
    ctx.fillStyle = 'rgb('+ red +','+ green +','+ blue +')';
    ctx.fill();    
    ctx.closePath();
    red = Math.min(Math.max(red - inc, 36))
    green = Math.max(green, Math.min(182, green + inc));
    blue = Math.max(blue, Math.min(255, blue + inc));

    requestAnimationFrame(animate);
}

animate();

这个想法是通过添加或减去名为inc(等于2)的变量来改变rgb的值。问题是,在矩形达到蓝色之前,它还会得到其他颜色(例如绿色)。这是因为绿色仅增加3个单位,但其他颜色仍需要时间来获取其新值。 示例: http://jsfiddle.net/f2Za8/ 有没有办法使“绿色”与“红色”和“蓝色”同时达到其新值?如何做到这一点?
2个回答

4

这个是否符合您的需求?

var debug = document.querySelector("#debug"),
    canvas = document.querySelector('#mycanvas'),
    ctx = canvas.getContext('2d'),
    red = 255,
    blue = 0,
    green = 179,
    tm = Date.now(),
    inc = 2;
    
function lerp(a, b, n) {
    return (b - a) * n + a;
}
    
function animate() {
    var n = (Date.now() - tm) * 0.001;
    n = Math.max(0, Math.min(1, n));
    
    red = lerp(255, 36, n) | 0;
    green = lerp(179, 182, n) | 0;
    blue = lerp(0, 255, n) | 0;
    
    debug.innerText = `${red} ${green} ${blue}`;
    
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.beginPath();
    ctx.rect(100, 100, 100, 100);
    ctx.fillStyle = `rgb(${red}, ${green}, ${blue})`;
    ctx.fill();    
    ctx.closePath();
    
    window.requestAnimationFrame(animate);
}
    
animate();
<p id="debug"></p>
<canvas id="mycanvas" width="600" height="400"></canvas>


1
+1,lerping在处理这种情况时总是简单而有效的。您可能希望在lerp中考虑提问者的inc=2;-) - markE

4
我会使用这个函数来灵活地控制想要淡入的颜色。
function blendColors(r1,g1,b1,r2,g2,b2,balance) {
    var bal = Math.min(Math.max(balance,0),1);
    var nbal = 1-bal;
    return {
            r : Math.floor(r1*nbal + r2*bal),
            g : Math.floor(g1*nbal + g2*bal),
            b : Math.floor(b1*nbal + b2*bal)
           };
} 

balance 的取值必须在 0 和 1 之间。因此可以在动画循环中增加一个变量,并将该变量作为平衡参数传递给 blendColors()

该函数返回具有 r、g 和 b 属性的对象。用法:

var blendedColor = blendColors(0,0,255,255,255,0,0.5);
// blendedColor.r contains 127;
// blendedColor.g contains 127;
// blendedColor.b contains 127;

我已经根据你的示例进行了适应: http://jsfiddle.net/f2Za8/7/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接