Alexander Hein Alexander Hein - 1 month ago 8
Javascript Question

How to change the color of a cube with Three.js

I would like to change the color of a cube based on a radio button selection. How can I achieve this with a smooth transition?

Radio button

<input id="black" type="radio" data-color="black" name="color" value="" checked="checked">
<input id="white" type="radio" data-color="white" name="color" value="">
<input id="blue" type="radio" data-color="chamois" name="color" value="">


Material

var color = {

"black": new THREE.MeshPhongMaterial({
color: 0x222222
}),
"white": new THREE.MeshPhongMaterial({
color: 0xffffff
}),
"chamois": new THREE.MeshPhongMaterial({
color: 0xEDE6D4
})

}


Geometry

var geometry= new THREE.BoxGeometry(2,2,2);
var mesh = new THREE.Mesh(geometry, color [ "black" ]);
scene.add(mesh );

Answer

Luckily for you, I implemented a solution to this a while ago - as long as you don't mind using a tweening library (I use GSAP), this code works great.

Here's the colour tweening code only (for brevity):

function colorTo (target, value){
    var target = scene.getObjectByName(target);
    var initial = new THREE.Color(target.material.color.getHex());
    var value = new THREE.Color(value.color.getHex());

    TweenLite.to(initial, 1, {     //This syntax is relevant to GSAP's TweenLite, I'll provide a link to the docs
        r: value.r,
        g: value.g,
        b: value.b,
        ease: Cubic.easeInOut,
        onUpdate: function() { target.material.color = initial; }
    });
}

Link to full code in fiddle

Remember, the reason why that fiddle works is because I'm linking to two external libraries:

  1. three.min.js
  2. TweenMax.min.js

If you have any questions, drop me a comment and I'll be sure to answer them!

Link to the GSAP TweenLite docs


EDIT

I've updated the answer to include functionality to trigger the tween with the radio buttons. It's important that when you create the mesh, you instantiate a new THREE.Material() instead of referencing a material already in the color array. Like so:

var mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: 0x222222})); 

Then linking it to the radio controls is no problem at all:

$("#inputs input").change(function(event){
    if ($(this).prop("checked")) {
        var targetColor = $(this).data("color");
        colorTo("box", color[targetColor]);
    }
});

EDIT 2

In the previous example I used a super lightweight tweening plugin (< 340 B) which unfortunately (unbeknownst to me) was pending retirement. I have since updated the example to use a slightly more generic, and thus heavier, library called GSAP - it is nonetheless an unbelievably capable and lightning fast library so I wouldn't hesitate to use it.

For the last time (hopefully), happy coding!