7

I have an three.js object which is a given colour. I want to animate it smoothly to another colour. During the animation, it should only show a direct gradation between the start and end. That is, it should not perform the tween linearly in RGB colour space. I'm not even sure that a linear tween within HSV space would look good either.

How can I get this kind of colour tween on a three.js object?

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742

1 Answers1

5

I have a version of this that makes a tween in HSV space. It's not perfect, as many different hues can appear along the way.

Three.js doesn't include a method for getting the HSV values from a THREE.Color. So, add one:

THREE.Color.prototype.getHSV = function()
{
    var rr, gg, bb,
        h, s,
        r = this.r,
        g = this.g,
        b = this.b,
        v = Math.max(r, g, b),
        diff = v - Math.min(r, g, b),
        diffc = function(c)
        {
            return (v - c) / 6 / diff + 1 / 2;
        };

    if (diff == 0) {
        h = s = 0;
    } else {
        s = diff / v;
        rr = diffc(r);
        gg = diffc(g);
        bb = diffc(b);

        if (r === v) {
            h = bb - gg;
        } else if (g === v) {
            h = (1 / 3) + rr - bb;
        } else if (b === v) {
            h = (2 / 3) + gg - rr;
        }
        if (h < 0) {
            h += 1;
        } else if (h > 1) {
            h -= 1;
        }
    }
    return {
        h: h,
        s: s,
        v: v
    };
};

Then, the tween is relatively straightforward:

new TWEEN.Tween(mesh.material.color.getHSV())
    .to({h: h, s: s, v: v}, 200)
    .easing(TWEEN.Easing.Quartic.In)
    .onUpdate(
        function()
        {
            mesh.material.color.setHSV(this.h, this.s, this.v);
        }
    )
    .start();

I'd be interested to hear of a more perceptually natural transition.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • 2
    What about doing the same but with rgb instead? `new TWEEN.Tween(mesh.material.color).to({r: 1, g: 0, b: 0 }, 200).start()` – mrdoob Sep 20 '12 at 08:46
  • @mrdoob, my past experiments with linear blending within RGB space tended to yield ugly intermediate colours. I'll try that out again though. For now, the above seems to work fairly well. – Drew Noakes Sep 20 '12 at 13:32
  • Ah. I misunderstood you. Yeah. Sounds like your approach is good. – mrdoob Sep 20 '12 at 16:44
  • How can I implement this into tween.js please? – thednp Oct 05 '14 at 15:02
  • 2
    Does anyone have a fiddlejs for this? I'm always getting `object.material.color.setHSV is not a function`... – binoculars May 16 '16 at 10:24