2016-11-21 144 views
3

我使用Web Animation API來創建一個簡單的動畫,以便當用戶在target上移動鼠標時,動畫應從左向右開始,當用戶將鼠標從target ,動畫應該顛倒過來,target應該從右向左移動。使用鼠標懸停和鼠標移動時避免生澀的動畫

當前,如果用戶在動畫過程中將鼠標移入/移出,動畫會變得不穩定,並且我沒有平滑的效果。

我想知道如何解決這個問題。

注意:目前我正在使用Web動畫API。但是在使用CSS關鍵幀動畫時會發生同樣的問題。

我也嘗試使用以下解決方案解決此問題,這改善了情況,但仍然存在問題。這是一個活生生的例子https://jsfiddle.net/x784xwoa/5/

var elm = document.getElementById("target"); 
 
var player = document.getElementById("target"); 
 

 
elm.addEventListener('mouseover', function(event) { 
 
    console.log('mouseover', player.playState, 'animate'); 
 
    player = elm.animate(
 
    [{ 
 
     left: "0px", 
 
     boxShadow: 'rgba(0, 0, 0, 0.5) 0px 0px 0px 0px' 
 
    }, { 
 
     left: "100px", 
 
     boxShadow: 'rgba(0, 0, 0, 0.9) 50px 150px 100px 0px' 
 
    }], { 
 
     duration: 3000, 
 
     direction: "normal", 
 
     fill: "forwards", 
 
     iterations: 1 
 
    } 
 
); 
 
}); 
 

 
elm.addEventListener('mouseout', function(event) { 
 
    console.log('mouseout', player.playState, 'reverse'); 
 
    player.reverse(); 
 
});
#target { 
 
    position: relative; 
 
    top: 0; 
 
    left: 0; 
 
    width: 100px; 
 
    height: 150px; 
 
    background-color: red; 
 
}
<div id="target"></div>

+0

你使用更新的codepen注意到了什麼?目前,Chrome和Firefox都在實施加法動畫(Web動畫的一部分),這將允許您製作一個可以平滑過渡到另一個的動畫。 – brianskold

回答

0

我能夠使用以下腳本添加一些邏輯來檢查playState以解決此問題。 如果您有更好的解決方案,請將其作爲答案張貼,因爲我真的有興趣收到您的反饋意見。

document.addEventListener("DOMContentLoaded", function (event) { 
 
      var elm = document.getElementById("target"); 
 
      var player = null; 
 

 

 

 
      elm.addEventListener('mouseenter', function (event) { 
 
       if (player === null) { 
 
        player = elm.animate(
 
         [{ 
 
          left: "0px", 
 
          boxShadow: 'rgba(0, 0, 0, 0.5) 0px 0px 0px 0px' 
 
         }, { 
 
          left: "100px", 
 
          boxShadow: 'rgba(0, 0, 0, 0.9) 50px 150px 100px 0px' 
 
         }], { 
 
          duration: 3000, 
 
          direction: "normal", 
 
          fill: "forwards", 
 
          iterations: 1 
 
         } 
 
        ); 
 
       } 
 
       else if (player.playState === 'running') { 
 
        player.reverse(); 
 
       } 
 
       else if (player.playState === 'finished') { 
 
        player.reverse(); 
 

 
       } 
 
      }); 
 

 
      elm.addEventListener('mouseout', function (event) { 
 
       if (player.playState === 'running' || player.playState === 'finished') { 
 
        player.reverse(); 
 
       } 
 
      }); 
 

 
      setInterval(function() { 
 
       if (player) { 
 
        console.log(player.playState); 
 
       } 
 
      }, 1000); 
 

 

 
     });
 #target { 
 
      position: relative; 
 
      top: 0; 
 
      left: 0; 
 
      width: 100px; 
 
      height: 150px; 
 
      background-color: red; 
 
     }
<div id="target"></div>

0

我一直使用的mouseenter/鼠標離開而不是鼠標懸停/鼠標移開取得了成功。

但是,雖然它們的操作方式相同,但只有當鼠標指針進入選定元素時纔會觸發mouseenter事件。如果鼠標指針也進入任何子元素,則會觸發mouseover事件。

+0

感謝您的評論,我已經嘗試了您的建議,不幸的是我仍然有相同的問題https://jsfiddle.net/r39f461s/2/ – GibboK

0

每次觸發鼠標懸停事件您爲元素一個新的動畫。通過事先創建動畫避免這種情況,並暫停它,直到它被使用。我也用player.playBackRate = (-)1;代替player.reverse();。我不確定爲什麼這也會造成問題。

var elm = document.getElementById("target"); 
 
var player = elm.animate(
 
    [{ 
 
    left: "0px", 
 
    boxShadow: 'rgba(0, 0, 0, 0.5) 0px 0px 0px 0px' 
 
    }, { 
 
    left: "100px", 
 
    boxShadow: 'rgba(0, 0, 0, 0.9) 50px 150px 100px 0px' 
 
    }], { 
 
    duration: 3000, 
 
    direction: "normal", 
 
    fill: "forwards", 
 
    iterations: 1 
 
    } 
 
); 
 
player.pause(); 
 

 
elm.addEventListener('mouseover', function(event) { 
 
    player.playbackRate = 1; 
 
    player.play(); 
 
}); 
 

 
elm.addEventListener('mouseout', function(event) { 
 
    player.playbackRate = -1; 
 
});
#target { 
 
    position: relative; 
 
    top: 0; 
 
    left: 0; 
 
    width: 100px; 
 
    height: 150px; 
 
    background-color: red; 
 
}
<div id="target"></div>

剩下的就是mouseout事件不火​​的唯一問題,當從鼠標下的元件運動。它只在鼠標移動時觸發。