簡體   English   中英

停止CSS在未知關鍵幀上平滑旋轉動畫

[英]Stop CSS rotate animation smoothly on unknown keyframe

我有一個使用CSS旋轉動畫擺動的圖像。 我想順利地停止它(當點擊另一個元素時將其恢復到原始位置但沒有得到跳躍的停止感覺)。 似乎預期的行為僅發生在動畫的第一次迭代中,而不是發生在即將發生的行為上(這是在前2秒內單擊“慢速”按鈕時)

這是一個示例代碼https://jsfiddle.net/pbarrientos/5v3xwak6/

我已經嘗試過添加animation-iteration-count:1; 和添加/刪除類。

var css = { 
        '-webkit-animation-iteration-count': "1",
        '-moz-animation-iteration-count': "1",
        'animation-iteration-count': "1"
    }

有線索嗎?

我會在這里使用手動動畫。 瀏覽器負責其CSS動畫,並且通過完美同步的位置和速度進行干預將是一項挑戰。

由於動畫不是很復雜,我們可以簡單地設置我們自己的矩陣,或使用輔助方法,以及使用正弦函數,其中半徑在停止時減少。

當按下停止按鈕時,我們減小半徑以使其看起來停止。 我們可以反過來重新開始。 好處是我們可以在任何時候停下來並自然休息。 如果要偏移角度,可以在減小半徑的同時插入到該角度。

通過使用requestAnimationFrame和變換,我們將獲得與CSS一樣的平滑動畫。

主要功能是:

angle = Math.sin(time) * radius;  // sin=[-1,1] radius => angle

然后在停止時,減小半徑,最終將成為角度:

radius *= 0.99;      

 var img = $("img"), btn = $("button"), angle, maxRadius = 10, radius = maxRadius, playing = true, time= 0; (function loop() { angle = Math.sin(time) * radius; // calc current angle setTransform(img, angle); if (playing) { if (radius < maxRadius) radius *= 1.03; // increase 3% each frame upto max } else { radius *= 0.99; // reduce 1% each frame } time += 0.1; requestAnimationFrame(loop) // loop, can be stopped when radius < n })(); function setTransform(img, angle) { img.css("transform", "rotate(" + angle + "deg)"); img.css("-webkit-transform", "rotate(" + angle + "deg)"); } btn.on("click", function() { playing = !playing; if (playing && radius < 0.1) radius = 0.1; // give some meat in case =0 }); 
 img { transform-origin: top center; -webkit-transform-origin: top center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <img src="http://i.stack.imgur.com/Vma8v.png"><br> <button>Start / Stop smoothly</button> 

當半徑小於n時,您可能希望實現一種中止循環的機制,然后在需要時啟動循環。 使用單獨的標志,以便消除啟動多個rAF的風險。

嘗試保存matrix的位置#element之前animation-play-state設置為paused ,加入救matrix的位置#elementcss應用到#element動畫暫停后; #play click事件#play animation-iteration-count重置為infinite - 例如,之前單擊#slow ,將animation-iteration-count1

 $(document).ready(function() { var el = $("#element"); // return `matrix` position of `el` `#element` function tfx(el) { return el.css(["-webkit-transform", "-moz-transform"]); } $("#pause").click(function() { // save `matrix` position of `el` var pos = tfx(el); var css = { "-webkit-animation-play-state": "paused", "-moz-animation-play-state": "paused", "animation-play-state": "paused" } // extend `css` with `pos` var _css = $.extend(pos, css); el.css(_css); }); $("#play").click(function() { // save `matrix` position of `el` var pos = tfx(el); // reset `animation-iteration-count` to `infinite` var css = { "-webkit-animation-iteration-count": "infinite", "-moz-animation-iteration-count": "infinite", "animation-iteration-count": "infinite", "-webkit-animation-play-state": "running", "-moz-animation-play-state": "running", "animation-play-state": "running" } // extend `css` with `pos` var _css = $.extend(pos, css); el.removeClass("stopit").addClass("swing").css(_css); }); $("#slow").click(function() { el.removeClass("swing").addClass("stopit"); var css = { "-webkit-transition": "all 4000ms ease-out", "-webkit-animation-iteration-count": "1", "-moz-animation-iteration-count": "1", "animation-iteration-count": "1" } el.css(css); // `stopit` class added above ? // el // .one("webkitAnimationEnd oanimationend msAnimationEnd animationend", function (e) { // el.addClass("stopit"); // }); }); }); 
 .swing { transform-origin: top center; -webkit-transform-origin: top center; animation: badge-swing 2s infinite; -webkit-animation: badge-swing 2s infinite; -webkit-animation-fill-mode: both; -webkit-animation-timing-function: ease-in-out; -moz-animation: badge-swing 2s infinite; -moz-animation-fill-mode: forwards; animation-fill-mode: forwards; } .stopit { -webkit-animation-duration: 2s; -webkit-animation-name: stopit; -webkit-animation-fill-mode: forwards; -moz-animation-duration: 2s; -moz-animation-name: stopit; -moz-animation-fill-mode: forwards; animation-name: stopit; } @-webkit-keyframes badge-swing { 0% { -webkit-transform: rotate(-5deg); -webkit-animation-timing-function: ease-in; } 25% { -webkit-transform: rotate(0deg); -webkit-animation-timing-function: ease-out; } 50% { -webkit-transform: rotate(5deg); -webkit-animation-timing-function: ease-in; } 75% { -webkit-transform: rotate(0deg); -webkit-animation-timing-function: ease-out; } 100% { -webkit-transform: rotate(-5deg); -webkit-animation-timing-function: ease-in; } } @-moz-keyframes badge-swing { 0% { -moz-transform: rotate(-5deg); -moz-animation-timing-function: ease-in; } 25% { -moz-transform: rotate(0deg); -moz-animation-timing-function: ease-out; } 50% { -moz-transform: rotate(5deg); -moz-animation-timing-function: ease-in; } 75% { -moz-transform: rotate(0deg); -moz-animation-timing-function: ease-out; } 100% { -moz-transform: rotate(-5deg); -moz-animation-timing-function: ease-in; } } @-webkit-keyframes stopit { 0% { -webkit-transform: rotate(-5deg); -webkit-animation-timing-function: ease-out; } 100% { -webkit-transform: rotate(0deg); -webkit-animation-timing-function: ease-out; } } @-moz-keyframes stopit { 0% { -moz-transform: rotate(-5deg); -moz-animation-timing-function: ease-out; } 100% { -moz-transform: rotate(0deg); -moz-animation-timing-function: ease-out; } } #pause, #play, #slow { display: inline-block; padding: 5px 30px; background: lightgrey; border-radius: 5px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <img id="element" src="https://dl.dropboxusercontent.com/u/39131788/palmed.png" class="swing"> <br> <br> <div id="pause">pause</div> <div id="play">play</div> <div id="slow">slow</div> 

jsfiddle https://jsfiddle.net/5v3xwak6/5/

如果你使用TweenMax會很有趣。

jsFiddle

片段:

 var element=document.getElementById('element'); var playButton=document.getElementById('play'); var pauseButton=document.getElementById('pause'); var slowButton=document.getElementById('slow'); var maxDegree=-10; var minDegree=10; var duration=.8; var easeFunc=Power2; var timeline=new TimelineMax({paused:true,repeat:-1}); TweenMax.set(element,{transformOrigin:'top center'}); timeline.to(element,duration,{rotation:maxDegree,ease:easeFunc.easeOut}); timeline.to(element,duration,{rotation:0,ease:easeFunc.easeIn}); timeline.to(element,duration,{rotation:minDegree,ease:easeFunc.easeOut}); timeline.to(element,duration,{rotation:0,ease:easeFunc.easeIn}); playButton.addEventListener('click',onPlayClick,false); pauseButton.addEventListener('click',onPauseClick,false); slowButton.addEventListener('click',onSlowClick,false); function onPlayClick(){timeline.timeScale(1).play();} function onPauseClick(){timeline.timeScale(1).pause();} function onSlowClick(){ timeline.pause().timeScale(.5); if(timeline.progress()<.25){ timeline.tweenTo(0); }else if(timeline.progress()>=.25&&timeline.progress()<.75){ timeline.tweenTo(timeline.duration()*.5); }else{ timeline.tweenTo(timeline.duration()); } } 
 #pause, #play, #slow { display: inline-block; padding: 5px 30px; background: lightgrey; border-radius: 5px; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script> <img id="element" src="https://dl.dropboxusercontent.com/u/39131788/palmed.png" class="swing"> <br> <br> <div id="pause">pause</div> <div id="play">play</div> <div id="slow">slow</div> 

如果您有興趣,目的是為您提供替代方案。 希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM