如何在anime.js中使用“seek”来控制滚动时的动画?请举个例子

Posted

技术标签:

【中文标题】如何在anime.js中使用“seek”来控制滚动时的动画?请举个例子【英文标题】:How to use "seek" in anime.js in order to control an animation while scrolling? With example, please 【发布时间】:2019-09-20 02:50:20 【问题描述】:

更新的anime.js文档(Controls->Seek)说可以在滚动的时候控制动画,但是没有例子。

谁能举例说明如何设置animation.seek?

https://animejs.com/documentation/#seekAnim

var animation = anime(
  targets: '.seek-anim-demo .el',
  translateX: 270,
  delay: function(el, i)  return i * 100; ,
  elasticity: 200,
  easing: 'easeInOutSine',
  autoplay: false
);

var seekProgressEl = document.querySelector('.seek-anim-demo .progress');
seekProgressEl.oninput = function() 
  animation.seek(animation.duration * (seekProgressEl.value / 100));
;

【问题讨论】:

【参考方案1】:

这就是你要找的。​​p>

javascript

function getScrollPercent() 
   var h = document.documentElement,
   b = document.body,
   st = 'scrollTop',
   sh = 'scrollHeight';
   return (h[st] || b[st]) / ((h[sh] || b[sh]) - h.clientHeight) * 100;
 
 const
 // parent = document.querySelector('.outerHeight'),
 els = document.querySelectorAll('.el'),
 tl = anime.timeline( autoplay: false );
    
 _.map(els, el => 
   anime.set(el, 
     top: anime.random(0, 150) + 'vh',
     left: anime.random(0, 100) + 'vw' );
    
   tl.add(
     targets: el,
     translateX: anime.random(-500, 500) + '%',
     translateY: anime.random(-500, 500) + '%',
     scale: anime.random(0.3, 1.7),
     rotate: anime.random(-365, 365) + 'deg',
     duration: anime.random(500, 5000), easing: 'easeInOutCirc' ,
   0);
 );
    
 // new AnimePlayer( add: tl )
    
 window.addEventListener('scroll', () => 
   const persentage = getScrollPercent();
   tl.seek(tl.duration * (persentage * 0.01));
);

来源:Codepen (https://codepen.io/gaougalos/pen/bJXYZa)

【讨论】:

非常感谢您的示例。您知道是否有任何方法可以添加阻尼/平滑效果?例如,当滚动停止时,动画不会突然停止:university.webflow.com/article/interpolation-easing-smoothing @mr1031011 不,我不知道,我认为如果不进行大量调整就无法完成,因为您想为滚动添加缓动,而 AnimeJS 为目标提供缓动(时间轴动画)。 我已经成功了,任何有兴趣的人都可以在这里查看更多信息:github.com/juliangarnier/anime/issues/703 我只想说谢谢你提到它是“缓和滚动”。你是绝对正确的,缓动必须应用于seek函数的触发器而不是seek本身。当我读到你的评论时,那一刻真是令人惊叹。【参考方案2】:

最后我找到了一个解决方案,使用 seek 和使用交叉点观察器来触发和控制动画。

但唯一的问题是 entry.boundingClientRect 不跟踪所有进度,而只跟踪触发器的进入或离开:

    let observer_imgs_parallax;
    let Element_imgs_parallax;

    let prevRatio = 0.0;
    let options_parallax = 
        root: null,
        rootMargin: '0px',
        threshold: buildThresholdList() //se parallax
    ;

    // Set things up
        Element_imgs_parallax = document.querySelector('.trigger-parallax-fake');
        initObserver_parallax();

    //////////////////////////////////////////////////////////////////////////////

    function initObserver_parallax() 
        observer_imgs_parallax = new IntersectionObserver(callback_imgs_parallax, options_parallax);
        observer_imgs_parallax.observe(Element_imgs_parallax);
    

    /////////////////////////////////////////////////////////////////////////////

    function buildThresholdList() 
    let thresholds = [];
    let numSteps = 200;
    for (let i=1.0; i<=numSteps; i++) 
        let ratio = i/numSteps;
        thresholds.push(ratio);
    
    thresholds.push(0);
    return thresholds;
    

    /////////////////////////////////////////////////////////////////////////////


    var animazione_parallax = anime (
        targets: '.immagini-parallax img',
        translateY: ['15%','-15%'],
        easing: 'easeInOutSine',
        duration: 1000,
        autoplay: false
    );


    ////////////////////////////////////////////////////////////////////////////


    //animazione parallax
    function callback_imgs_parallax (entries, observer_imgs_parallax) 
    entries.forEach((entry) => 
    if(entry.boundingClientRect.top < 0) //osservazione elemento da top

        animazione_parallax.seek(animazione_parallax.duration * (entry.intersectionRatio)); //parallax

    else animazione_parallax.seek(1000); //posizione dopo il passaggio
    prevRatio = entry.intersectionRatio; //rimuove se non parallax
    );
    

现在我网站中的每个动画都由交叉点观察器触发或控制,并由anime.js制作

链接:https://alessiopaolettidesign.it

【讨论】:

以上是关于如何在anime.js中使用“seek”来控制滚动时的动画?请举个例子的主要内容,如果未能解决你的问题,请参考以下文章

anime.js 实战:实现一个带有描边动画效果的复选框

基于滚动值的 Flutter Web 视频播放

markdown 带有anime.js的SVG球体动画

markdown 带有anime.js的SVG球体动画

C#的自定义滚动条

typescript animejs / anime.js TypeScript的类型定义。另请参见https://github.com/kohashi/types-npm-animejs