Updating the DeltaY clock in three.js based on scroll position (top or bottom)

I am looking for a way to reset the animation prototype on scroll. Currently, the animation loops continuously and does not stop at the top or bottom. I want the animation to play forward when scrolled from the top and in reverse when it reaches the bottom.

 var container, stats, controls;
      var camera, scene, renderer, light;
      var clock = new THREE.Clock();

      var mixer = [];

      var mixers = [];

      init();

      animate();

      function init() {

        container = document.createElement( 'div' );
        document.body.appendChild( container );

        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set( 0, 100, 100 );

        scene = new THREE.Scene();

        light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
        light.position.set( 0, 200, 0 );
        scene.add( light );

        light = new THREE.DirectionalLight( 0xffffff );
        light.position.set( 0, 200, 100 );
        light.castShadow = true;
        light.shadow.camera.top = 180;
        light.shadow.camera.bottom = -100;
        light.shadow.camera.left = -120;
        light.shadow.camera.right = 120;
        scene.add( light );

          // scene.add( new THREE.CameraHelper( light.shadow.camera ) );

          var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
          grid.material.opacity = 0.2;
          grid.material.transparent = true;
          scene.add( grid );

          // model
          var loader = new THREE.FBXLoader();
          loader.load( 'https://threejs.org/examples/models/fbx/Samba Dancing.fbx', function ( object ) {

            object.mixer = new THREE.AnimationMixer( object );
            mixers.push( object.mixer );


            var action = object.mixer.clipAction( object.animations[ 0 ] );
            action.play();


            object.traverse( function ( child ) {

              if ( child.isMesh ) {

                child.castShadow = true;
                child.receiveShadow = true;

              }

            } );
            object.position.y = 85;

            scene.add( object );

          } );


          renderer = new THREE.WebGLRenderer( { alpha: true, antialias: true } );
          renderer.setPixelRatio( window.devicePixelRatio );
          renderer.setSize( window.innerWidth, window.innerHeight );
          renderer.shadowMap.enabled = true;
          container.appendChild( renderer.domElement );

          window.addEventListener( 'mousewheel', onMouseWheel, false );
          window.addEventListener( 'touchstart', onTouchStart, false );
          window.addEventListener( 'touchmove', onTouchMove, false );

          window.addEventListener('resize', onResize, false);

          // stats
          stats = new Stats();
          container.appendChild( stats.dom );

        }


        function onResize() {
          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix();
          renderer.setSize(window.innerWidth, window.innerHeight);
        }


        function onMouseWheel( event ) {


          if(event.deltaY > 0){
            for ( var i = 0; i < mixers.length; i ++ ) {
              mixers[ i ].update( clock.getDelta() * 5 );
            }
          } else {
            for ( var i = 0; i < mixers.length; i ++ ) {
              mixers[ i ].update( clock.getDelta() * -5 );

            }
          }
        }


        function onTouchStart(event) {

          startY = event.touches[ 0 ].pageY;


        }

        function onTouchMove( event ) {

          var delta = event.deltaY;

          if(event.deltaY > 0){
            for ( var i = 0; i < mixers.length; i ++ ) {
              mixers[ i ].update( clock.getDelta() * 5 );
            }
          } else {
            for ( var i = 0; i < mixers.length; i ++ ) {
              mixers[ i ].update( clock.getDelta() * -5 );

            }
          }


        }


        function animate() {

         delta = clock.getDelta();

         requestAnimationFrame( animate );

         renderer.render( scene, camera );

         stats.update();

       }
body {

        margin: 0px;
        overflow: hidden;
      }
     <script src="https://threejs.org/build/three.js"></script>
       <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
      <script src="https://threejs.org/examples/js/libs/inflate.min.js"></script>
       <script src="https://threejs.org/examples/js/loaders/FBXLoader.js"></script>
         <script src="https://threejs.org/examples/js/WebGL.js"></script>
          <script src="https://threejs.org/examples/js/libs/stats.min.js"></script>

Answer №1

It is highly recommended to avoid directly linking to threejs.org. If the version of Three.js is updated by the developers, your example could become irrelevant to others. Instead, consider using a specific version from a CDN!

Another approach is to save the clips

object.mixer = new THREE.AnimationMixer( object );
mixers.push( object.mixer );

const clip = object.animations[0];
clips.push(clip);
var action = object.mixer.clipAction(clip);
action.play();

Incorporate code similar to this to handle the animations

function updateAnimation(direction) {
  const delta = direction * 5 * clock.getDelta();
  for (let i = 0; i < mixers.length; ++i) {
    const mixer = mixers[i];
    const clip = clips[i];
    const duration = clip.duration;
    const newTime = THREE.MathUtils.clamp(mixer.time + delta, 0, duration);
    mixer.setTime(newTime);
  }
}


function onMouseWheel( event ) {
  updateAnimation(Math.sign(event.deltaY)); 
}

...

var container, stats, controls;
  var camera, scene, renderer, light;
  var duration;
  var clock = new THREE.Clock();

  var mixer = [];

  var mixers = [];
  var clips = [];

  init();

  animate();

  function init() {

    container = document.createElement('div');
    document.body.appendChild(container);

    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 100, 100);

    scene = new THREE.Scene();

    light = new THREE.HemisphereLight(0xffffff, 0x444444);
    light.position.set(0, 200, 0);
    scene.add(light);

    light = new THREE.DirectionalLight(0xffffff);
    light.position.set(0, 200, 100);
    light.castShadow = true;
    light.shadow.camera.top = 180;
    light.shadow.camera.bottom = -100;
    light.shadow.camera.left = -120;
    light.shadow.camera.right = 120;
    scene.add(light);

    var grid = new THREE.GridHelper(2000, 20, 0x000000, 0x000000);
    grid.material.opacity = 0.2;
    grid.material.transparent = true;
    scene.add(grid);

    var loader = new THREE.FBXLoader();
    loader.load('https://threejs.org/examples/models/fbx/Samba Dancing.fbx', function (object) {

      object.mixer = new THREE.AnimationMixer(object);
      mixers.push(object.mixer);

      const clip = object.animations[0];
      clips.push(clip);
      var action = object.mixer.clipAction(clip);
      action.play();

      object.traverse(function (child) {

        if (child.isMesh) {

          child.castShadow = true;
          child.receiveShadow = true;

        }

      });
      object.position.y = 85;

      scene.add(object);

    });

    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    container.appendChild(renderer.domElement);

    window.addEventListener('mousewheel', onMouseWheel, false);

    window.addEventListener('resize', onResize, false);

    stats = new Stats();
    container.appendChild(stats.dom);

  }

  function onResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }

  function updateAnimation(direction) {
    const delta = direction * 5 * clock.getDelta();
    for (let i = 0; i < mixers.length; ++i) {
      const mixer = mixers[i];
      const clip = clips[i];
      const duration = clip.duration;
      const newTime = THREE.MathUtils.clamp(mixer.time + delta, 0, duration);
      mixer.setTime(newTime);
    }
  }

  function onMouseWheel(event) {
    updateAnimation(Math.sign(event.deltaY));
  }

  function animate() {

    delta = clock.getDelta();

    requestAnimationFrame(animate);

    renderer.render(scene, camera);

    stats.update();

  }
body {

  margin: 0px;
  overflow: hidden;
}
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0b4a8b2a5a580f0eef1f1f3eef2">[email protected]</a>/build/three.min.js"></script>
       <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0c78647e69694c3c223d3d3f223e">[email protected]</a>/examples/js/controls/OrbitControls.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="55213d27303015655f6f5f7d6b6d7c79746e7772737c2d0b070f">[email protected]</a>/examples/js/libs/inflate.min.js"></script>
       <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="205448524545601017175e4c504f5b454f15515f">[email protected]</a>/examples/js/loaders/FBXLoader.js"></script>
         <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cabea2b8afaf8afae8bab8a9a0a2baa3ae96a1aba8bd95a1adbd">[email protected]</a>/examples/js/WebGL.js"></script>
          <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0c78647e69694c3c223d3d3f223e">[email protected]</a>/examples/js/libs/stats.min.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the reason that preventDefault fails but return false succeeds in stopping the default behavior

I'm having trouble with my preventDefault code not working as expected. While using return false seems to work fine, I've heard that it's not the best practice. Any ideas why this might be happening? if ($('.signup').length == 0) ...

The functionality of jQuery's toggleClass is not functioning properly when clicking on a different thumbnail

My objective: I want to display a set of thumbnails. When a thumbnail is clicked, I want to toggle the hiddenElement class and show a large image inside a hidden div. If anywhere in the DOM is clicked, it should hide the current image or allow the user t ...

The Twilio API is failing to deliver the response in JSON format

I have been working on an API to send WhatsApp responses to clients using Twilio as the service provider. However, I am encountering a problem where I am unable to receive the response in JSON format, despite following the code examples provided by Twilio. ...

Clear Dropdown Selections prior to Submitting

When trying to change the value of the first dropdown list and reset the second dropdown before submission, I encountered an issue where the second dropdown still retains its previous selection upon submission. There is no submit button as the form is subm ...

Creating a div resizing function using only JavaScript is a fun and useful project to tackle

Seeking help to create a div resizer using only pure JavaScript as jQuery is restricted. The current functionality works, but breaks when the position of the slider-div is not set to absolute. Any solutions to fix this issue would be greatly appreciated. ...

The returned state from setState(prev) seems to be in the opposite order when referencing another useState variable within a useEffect

As part of my interactive chat simulation project, I have implemented a feature where users can click on a button named obj4 to start their chat session. Initially, everything functions smoothly, displaying messages 1-4 in the correct order. However, when ...

Monitoring and recording Ajax requests, and retrying them if they were unsuccessful

As a newcomer to Javascript, I'm diving into the world of userscripts with the goal of tracking all Ajax calls within a specific website. My objective is to automatically repeat any failed requests that do not return a status code of 200. The catch? T ...

Utilize a variable within an HTML attribute

Currently utilizing Angular and I have the following HTML snippet <input onKeyDown="if(this.value.length==12 && event.keyCode!=8) return false;"/> Is there a way for me to incorporate the variable "myNum" instead of the ...

Looping through ViewData strings and populating a form with their values

I am currently utilizing ASP.NET and MVC to work on a project where I need to take a list of strings and populate a form with them. The goal is for users to import account numbers, have the form prefilled with these numbers, and then submit the data. I&apo ...

display upcoming schedule and time

How can I display the future date and time in the respective field components? See below for a sample code snippet: require([ "dojo/_base/lang", "dijit/registry", "dojo/ready", "dijit/form/TimeTextBox", "dojo/parser" ], function(lang, registry, ready ...

window.onresize = function() { // code here

Here's an example of code I've been working on: $(document).ready(function (e) { adjustSize(); $(window).resize(adjustSize); function adjustSize() { var windowWidth = parseInt($(window).width()); if (windowWidth > ...

Is it possible to perform cross domain AJAX calls while implementing Basic Authentication?

Having a ColdFusion application located behind an ISA Server presents some challenges. In this case, part of the application requires Basic Authentication while another part does not. The issue arises when trying to access cookies set by the ISA Server upo ...

Inject Dynamic HTML Content onto the Page or in a Pop-up Box

I am currently working on a C# asp.net Web Forms project that involves a credit card payment system. The system returns HTML code for a 3D payment page, but it does not auto-redirect. Here is a snippet of my request: thirdBasketItem.Price = "0.2"; basketI ...

Attempting to adjust the width of a text animation loaded with jQuery using Textillate, but encountering difficulties

I found a captivating animation on this website: http://codepen.io/jschr/pen/GaJCi Currently, I am integrating it into my project. #content { position: relative; margin-left: auto; margin-right: auto; width: 1000px; height: 700px; } ...

Implement a function to trigger and refresh components in various Vuejs2 instances simultaneously

I currently have index.html with two Vue instances in different files: <!DOCTYPE html> <html lang="en"> <body> <div id="appOne"> </div> <div id="appTwo"> </div> </body> </html ...

Guide to displaying options in the Vue material select box even when the default value is blank

I have implemented the material design framework vuematerial with vue.js. In traditional HTML, a selection box looks like this: <select> <option value="">You should initially see this</option> <option value="1">One</o ...

Tracking the last time an app was run in Javascript can be achieved by creating a variable to store the date when

Exploring the world of Javascript as a newbie, I find myself with index.html, stylesheet.css and div.js in my app. Within div.js lies a code that magically generates a schedule for our team members over 2 weeks. However, there's a catch - consistency ...

Adjusting the transparency of the object's interior

I used the side property to give my object an interior, but it also reflects the exterior: let material = new THREE.MeshStandardMaterial({side: THREE.DoubleSide}); https://i.sstatic.net/oikad.png https://i.sstatic.net/Vb03K.png Is there a way to red ...

Exploration of frontend utilization of web API resources

I've come across this issue multiple times. Whenever I modify a resource's result or parameters and search for where it's utilized, I always end up overlooking some hidden part of the application. Do you have any effective techniques to loc ...

Combining multiple directories into a single output using the rollup command

Alright, let's talk about my directory setup: mods/ -core/ --index.js --scripts/ ---lots of stuff imported by core/index Currently, the typical rollup process works smoothly if you want to create something like mods/core/index.min.js. However, I ha ...