'THREE.JS Mesh position smooth animation

I have a pretty easy question for you with three.js about x position translation of an imported .obj mesh.

I'm fairly new to three.js and was wandering if someone could give me some lead on what to do or solve this problem.

So... I have this mesh on (0,-200,0) and i just wanted to move it to (50,-200,0) with a smooth translation through a button back and forth to the two positions.

objLoader = new THREE.OBJLoader();
 objLoader.load('models/map_real.obj', function (obj) {

      var blackMat = new THREE.MeshStandardMaterial({color:0xfaf9c9});
      obj.traverse(function (child) {

         if (child instanceof THREE.Mesh) {
             child.material = blackMat;
         }

     });
     obj.castShadow = true;
     obj.receiveShadow = true;
     obj.position.set(0,-200,0)
     obj.rotation.y = getDeg(-20);
     scene.add(obj);
     objWrap = obj;

 });

I have in my main.js an init() which contains all the functions such as camera(), animate(), render() etc... and from the variable objWrap.position.x it logs the correct position.

I've tried to capture the click (as the snippet below shows) on my #test button and only increment the position by 0.5 - - i get this, is not in the animate loop so it cant keep add 0.5.

$('#test').click(function(){
    if (objWrap.position.x <= 50) {
    objWrap.position += 0.5}
});

So the final result that i want is a button that toggle back and forth a smooth animation that goes from objWrap.position.x = 0 to objWrap.position.x = 50

I hope to have been clear, feel free to ask if you need to know more, i'll respond in seconds... All the help is truly appreciate!



Solution 1:[1]

Just an example of how you can do it with Tween.js:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.setScalar(50);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

scene.add(new THREE.GridHelper(200, 100));

var box = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), new THREE.MeshBasicMaterial({
  color: "aqua"
}));
scene.add(box);

btnMove.addEventListener("click", onClick, false);

var forth = true;

function onClick() {

  new TWEEN.Tween(box.position)
    .to(box.position.clone().setX(forth ? 50 : 0), 1000)
    .onStart(function() {
      btnMove.disabled = true;
    })
    .onComplete(function() {
      btnMove.disabled = false;
      forth = !forth;
    })
    .start();

}

render();

function render() {
  requestAnimationFrame(render);
  TWEEN.update();
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script>
<button id="btnMove" style="position:absolute;">Move</button>

Solution 2:[2]

This works with ReactJS,

import TWEEN.

import {TWEEN} from "three/examples/jsm/libs/tween.module.min";

Enable drag controller and tween animation.

const { gl, camera } = useThree();
const objects = [];   // objects.push(ref.current)

useEffect(() => {
    const controls = new DragControls( objects, camera, gl.domElement );

    controls.addEventListener( 'dragend', (e) => {
         new TWEEN.Tween(e.object.position)
             .to(new Vector3(x, y, z), 1000)
             .easing(TWEEN.Easing.Back.InOut)
             .start();
    });
})

UseFrame to show the animation.

useFrame(() => {
    TWEEN.update();
});

Hope to help someone.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 prisoner849
Solution 2 Thushara Buddhika