简体   繁体   中英

Javascript mousemove animation angle needs to go slowly back to Zero

 const initEyeMove = () => { let eyeBall = document.querySelector(`.eyeball`); let pupil = document.querySelector(`.pupil`); if (eyeBall && pupil) { let eyeArea = eyeBall.getBoundingClientRect(); let pupilArea = pupil.getBoundingClientRect(); let R = eyeArea.width / 2; let r = pupilArea.width / 2; let centerX = eyeArea.left + R; let centerY = eyeArea.top + R; document.addEventListener(`mousemove`, (e) => { let x = e.clientX - centerX; let y = e.clientY - centerY; let theta = Math.atan2(y, x); let angle = theta * 180 / Math.PI + 360; if (angle < 330 || angle > 380) { angle = 0; } pupil.style.transform = `translateX(${R - r + `px`}) rotate(${angle + `deg`})`; pupil.style.transformOrigin = `${r + `px`} center`; }); } }; initEyeMove();
 .pupil { background-color: transparent; width: 1px; height: 1px; border-radius: 50%; }.pupil svg { top: 50%; left: 50%; transform: translate(30%, 30%); }.eye { position: absolute; top: 1px; left: 6px; }.eyeball { width: 10px; height: 10px; background-color: none; position: absolute; top: 120px; left: 6px; }
 <div class="eyeball"> <div class="pupil"> <svg xmlns="http://www.w3.org/2000/svg"> <defs> <style>.cls-2{fill-rule:evenodd} </style> </defs> <g id="Слой_2" data-name="Слой 2"> <g id="Слой_1-2" data-name="Слой 1"> <g id="Untitled"> <path fill="#ff0" fill-rule="evenodd" stroke="#ff0" stroke-linecap="round" stroke-linejoin="round" stroke-width="10" d="M5 71.4C5 34.7 37.3 5 77.1 5s72.1 29.7 72.1 66.4-32.3 66.4-72.1 66.4S5 108 5 71.4z"/> <path d="M59.9 31.3a15.2 15.2 0 1115.2 15.2 15.19 15.19 0 01-15.2-15.2zM82 75.3c2.9-19.8 16.7-35.4 30.8-34.9s23.1 16.9 20.2 36.7-16.7 35.4-30.8 34.9S79.1 95.1 82 75.3z" class="cls-2"/> </g> </g> </g> </svg> </div> </div>

Have an if statement that makes an angle of an element on mousemove go back to zero under certain conditions. Need to make it go slowly back to zero from an angle that it had before going out of the set conditions.

Update: added more details, want this eyellow eye go back to start position smoother, not innediately when angle is more or less than needed.

To return it back to normal, you will have to use an animationFrame to adjust it on a frame by frame basis. I think the easiest way to do that is making the calculations and the application of your angle separate, and then allowing a method to continue calling the reduction in your angle. As I'm not sure what the end result is, the following is just a guess (and it assumes does your angle goes back to 0):

 const initEyeMove = () => { let eyeBall = document.querySelector(`.eyeball`); let pupil = document.querySelector(`.pupil`); if (eyeBall && pupil) { let eyeArea = eyeBall.getBoundingClientRect(); let pupilArea = pupil.getBoundingClientRect(); let R = eyeArea.width / 2; let r = pupilArea.width / 2; let centerX = eyeArea.left + R; let centerY = eyeArea.top + R; // Store this globally so both your methods can access and change it let angle = 0; function undoPupil( t ){ // Reduce the angle, limit it, etc... angle -= 1; angle = angle < 0? 0: angle; // Only request an animation frame if the angle needs to change further if( angle > 0 ) window.requestAnimationFrame( applyPupil ); } function applyPupil( angle ){ pupil.style.transform = `translateX(${R - r + `px`}) rotate(${angle + `deg`})`; pupil.style.transformOrigin = `${r + `px`} center`; // Start undoing the angle here undoPupil(); } document.addEventListener(`mousemove`, (e) => { let x = e.clientX - centerX; let y = e.clientY - centerY; let theta = Math.atan2(y, x); angle = theta * 180 / Math.PI + 360; applyPupil(); }); } }; export {initEyeMove};

If you want a smoother experience, or one where you can control the duration, you could go the following route, where we store the time and use it to calculate the delta so we can apply it over a given time:

 const initEyeMove = () => { let eyeBall = document.querySelector(`.eyeball`); let pupil = document.querySelector(`.pupil`); if (eyeBall && pupil) { let eyeArea = eyeBall.getBoundingClientRect(); let pupilArea = pupil.getBoundingClientRect(); let R = eyeArea.width / 2; let r = pupilArea.width / 2; let centerX = eyeArea.left + R; let centerY = eyeArea.top + R; let angle = 0; // We will store the time the animation frame gets called here let time = 0; // Store the duration as well. let duration = 5000; function undoPupil( t ){ const delta = time - t; time = t; // Reduce the angle, limit it, etc... angle *= 1 - (delta / duration); angle = angle < 0? 0: angle; // Only request an animation frame if the angle needs to change further if( angle > 0 ) window.requestAnimationFrame( applyPupil ); } function applyPupil( angle ){ pupil.style.transform = `translateX(${R - r + `px`}) rotate(${angle + `deg`})`; pupil.style.transformOrigin = `${r + `px`} center`; // Start undoing the angle here undoPupil(); } document.addEventListener(`mousemove`, (e) => { let x = e.clientX - centerX; let y = e.clientY - centerY; let theta = Math.atan2(y, x); angle = theta * 180 / Math.PI + 360; time = window.performance? window.performance.now(): Date.now() applyPupil(); }); } }; export {initEyeMove};

Please note that I have not tested these, as I have no context for what is supposed to happen. Add your HTML and perhaps some code to show of the effect you want in a snippet here in SO, then we can help you further.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM