Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 );
like image 806
Alexander Hein Avatar asked Aug 27 '15 14:08

Alexander Hein


Video Answer


2 Answers

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!

like image 120
jonny Avatar answered Sep 27 '22 21:09

jonny


I found the color of material can be tweened directly!

var targetColor = new THREE.Color(0xafe2f3);
TweenMax.to( object.material.color, 2, {
                r: targetColor.r,
                g: targetColor.g,
                b: targetColor.b
});
like image 41
Laura Juo-Hsin Chen Avatar answered Sep 27 '22 21:09

Laura Juo-Hsin Chen