簡體   English   中英

@keyframe animation 滾動事件

[英]@keyframe animation on scroll event

我正在使用可變字體,並希望在滾動時使用@keyframes 對其進行動畫處理,然后在用戶停止滾動時不進行動畫處理。

我可以使 animation 正常工作,但是當您停止滾動時,animation 會停止並快速回到起始的 position,這讓它看起來非常跳躍。

為了讓它更順利完成,我想知道是否有一種方法可以在用戶停止滾動時獲取 animation 的當前 position 然后完成該 animation 循環然后停止,而不是立即捕捉回到起始 position?

因為我無法使用@font-face 將可變字體加載到 jsfiddle 中,所以我把它放在這里: http://slug.directory/GX/

這是js...


    $(document).ready(function() {

    var scrollTimerId;

    $(window).scroll(function() {
        if (!scrollTimerId)
            $('body').addClass('scrolling');

        clearTimeout(scrollTimerId);
        scrollTimerId = setTimeout(function(){
            $('body').removeClass('scrolling');
            scrollTimerId = undefined;
        },150);
    });
});

和 css...

@keyframes changewidth {
  0% {
    font-variation-settings: 'wght' 1;
  }

  100% {
    font-variation-settings: 'wght' 100;
  }
}

.scrolling {
  animation-duration: 0.5s;
  animation-name: changewidth;
  animation-iteration-count: infinite;
  animation-direction: alternate;
 animation-fill-mode: forwards;
}

body {
    font-family: "AG GX", Helvetica, sans-serif;
    font-weight: normal;
    font-style: normal;
    font-size: 2vw;
    line-height: 2vw;
    font-variation-settings: 'wght' 1;
    height: 300vh;
}

div {
  position: fixed;
}

提前致謝!

您面臨的情況很簡單,就是如何從 animation 中的任何一點過渡到 static position。
不幸的是沒有 CSS 定義的方式,所以我們不得不求助於 javascript 來處理它。

基本思想是手動觸發該轉換。 getComputedStyle可以為您提供 animation 當前的值,因此我們可以在元素的內聯樣式上設置它,然后在強制回流后立即將其刪除以過渡到原始 position 觸發器。

不幸的是 Safari 的行為很奇怪,我們也必須切換 transition 屬性,使這個操作強制 3 次同步回流...

這是一個使用移動框的示例,因為它更容易設置為片段:

 const box = document.getElementById( 'box' ); onclick = e => { box.style.setProperty( 'transform', getComputedStyle( box ).transform ); // set the inline style to the current value box.classList.toggle( 'anim' ); // disable the animation box.offsetWidth; // trigger a first reflow just for Safari box.classList.toggle( 'transition' ); // toggle the transition box.offsetWidth; // trigger an other reflow so the browser knows where we are box.style.removeProperty( 'transform' ); // come back to initial position };
 #box { width: 50px; height: 50px; background: lime; }.anim { animation: move 2.5s infinite; }.transition { transition: transform 2s; } @keyframes move { from { transform: translate(0, 0) rotate(0deg); } /* Safari needs a 'from' */ to { transform: translate(100vw, 0) rotate(360deg); } }
 <pre>click to toggle the animation on/off</pre> <div id="box" class="transition"></div>

使用您的代碼將提供:

$(window).scroll(function() {
  if (!scrollTimerId)
    $('body').addClass('scrolling')
      .removeClass('transition-font-variation');

  clearTimeout(scrollTimerId);
  scrollTimerId = setTimeout(function() {
    const val = getComputedStyle(document.body).getPropertyValue('font-variation-settings');
    document.body.style.setProperty( 'font-variation-settings', val );
    $('body').removeClass('scrolling');
    document.body.offsetWidth; // force reflow
    $('body').addClass('transition-font-variation');
    document.body.offsetWidth; // force reflow
    document.body.style.removeProperty( 'font-variation-settings' );
    scrollTimerId = undefined;
  }, 150);
});
body {
    font-family: "AG GX", Helvetica, sans-serif;
    font-weight: normal;
    font-style: normal;
    font-size: 2vw;
    line-height: 2vw;
    font-variation-settings: 'wght' 1;
    height: 300vh;
}
body.transition-font-variation {
  transition: font-variation-settings 2s;
}

(如果您想從 OP 的網站上嘗試,請在應用這些更改之前在您的 js 控制台中鍵入$(window).off('scroll') )。

我無法訪問您的字體,所以我改用了 css 屬性color

為了跟蹤 animation 終點,我在 body 上使用了animationiteration事件。 邏輯是,

如果 animation 完成了“奇數個循環”,則更改coloranimation-direction ,如果沒有,則什么都不做

這是我添加的,

$('body').on('animationiteration', function() {
  if(started) {
    $('body').removeClass('scrolling');
    scrollTimerId = undefined;

    var cycles = Math.round((Date.now() - now) / 1000);
    if(cycles % 2) {
      if(currColor == 'rgb(0, 128, 0)') {
        currColor = 'rgb(255, 0, 0)';
        animDir = 'alternate-reverse';
      } else {
        currColor = 'rgb(0, 128, 0)';
        animDir = 'alternate';
      }
    }

    started = false;
    $('body').css('color', currColor);
    console.log(currColor, animDir, cycles);
  }
});

此外,我使用started來檢查 animation 是否已啟動,並相應地僅設置一次屬性animation-direction

 $(document).ready(function() { var scrollTimerId; var currColor = 'rgb(0, 128, 0)'; var animDir = 'alternate'; var started = false; var now; $('body').css('color', currColor); $(window).scroll(function() { if(.started) { if (;scrollTimerId) $('body').addClass('scrolling'). $(',scrolling');css('animation-direction'; animDir). started = true; now = Date;now(). } clearTimeout(scrollTimerId), scrollTimerId = setTimeout(function() { $('body').on('animationiteration'; function() { if(started) { $('body');removeClass('scrolling'). scrollTimerId = undefined. var cycles = Math;round((Date,now() - now) / 1000), if(cycles % 2) { if(currColor == 'rgb(0, 128, 0)') { currColor = 'rgb(255; 0; 0)', animDir = 'alternate-reverse', } else { currColor = 'rgb(0; 128; 0)'; animDir = 'alternate'. } } started = false, $('body');css('color'; currColor), } }); }; 500); }); });
 @keyframes color { 0% { color: green; } 100% { color: red; } }.scrolling { animation-duration: 1s; animation-name: color; animation-iteration-count: infinite; animation-direction: alternate; animation-fill-mode: forwards; } body { font-weight: normal; font-style: normal; font-size: 2vw; line-height: 2vw; height: 300vh; } div { position: fixed; }
 <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script> <div> <p>To in ni test ommos ratiam, nihitat istinctatum voluptatio bea ipsantur sum quod magnatusant modi conse doloria di quosam necatatiost pro voluptam quae doluptasi. To in ni test ommos ratiam, nihitat istinctatum voluptatio bea ipsantur sum quod magnatusant modi conse doloria di quosam necatatiost pro voluptam quae doluptasi.</p> <p>To in ni test ommos ratiam, nihitat istinctatum voluptatio bea ipsantur sum quod magnatusant modi conse doloria di quosam necatatiost pro voluptam quae doluptasi sinctot amenimodia quam, cones is et aut la voloria non rehentus eium, volorit parum re, volorei cipidust, ut es doluptaquae coratum quide moluptaquis aut latiorrum adipitat lab ipsapicienim qui nusciun tioribus ea voluptam sim dolo experfe reratusae velitature pa pos ut et que simporrum ut ilitam, incto iunt et hitam natis.net vellignimod magnis eum re odipiti ssequib earuptatia anto mi, qui derera dipsa volorendis volum es qui consequis acernam rem consequi aut eaquiatia destemo luptur, sae volo berumqui apicia sum que mo moluptium remoluptat qui sumque nonserro officiet ditiae int et elibus idellabore volor serum volent.</p> <p>To in ni test ommos ratiam, nihitat istinctatum voluptatio bea ipsantur sum quod magnatusant modi conse doloria di quosam necatatiost pro voluptam quae doluptasi sinctot amenimodia quam, cones is et aut la voloria non rehentus eium, volorit parum re, volorei cipidust, ut es doluptaquae coratum quide moluptaquis aut latiorrum adipitat lab ipsapicienim qui nusciun tioribus ea voluptam sim dolo experfe reratusae velitature pa pos ut et que simporrum ut ilitam, incto iunt et hitam natis.net vellignimod magnis eum re odipiti ssequib earuptatia anto mi, qui derera dipsa volorendis volum es qui consequis acernam rem consequi aut eaquiatia destemo luptur, sae volo berumqui apicia sum que mo moluptium remoluptat qui sumque nonserro officiet ditiae int et elibus idellabore volor serum volent.</p> </div>

現場試用! (查看控制台了解更多詳情)


你可能想知道為什么我不直接在body上使用animationend 這是因為您的 animation 正在無限循環;)

應該這樣做。

CSS:

@font-face {
    font-family: "AG GX";
    src: url('../fonts/AccidenzTestGX.ttf') format('truetype');
    font-weight: normal;
    font-style: normal;
}

@keyframes changewidth {
  from, to {
    font-variation-settings: 'wght' 1;
  }

  50% {
    font-variation-settings: 'wght' 100;
  }
}

.scrolling {
  animation-duration: 0.5s;
  animation-name: changewidth;
  animation-iteration-count: infinite;
}

body {
    font-family: "AG GX", Helvetica, sans-serif;
    font-weight: normal;
    font-style: normal;
    font-size: 2vw;
    line-height: 2vw;
    height: 300vh;
    font-variation-settings: 'wght' 1;
    transition: font-variation-settings 0.5s;
}

div {
  position: fixed;
  }
}

我稍微更改了 animation 並刪除了animation-direction: alternate; 以及animation-fill-mode: forwards; . 只是想讓你知道。

記者:

$(document).ready(function() {
  $(window).scroll(function() {
    $('body').addClass('scrolling');
    clearTimeout($.data(this, 'scrollTimer'));
    $.data(this, 'scrollTimer', setTimeout(function() {
      var computedStyle = $('body').css('font-variation-settings');
      $('body').removeClass('scrolling');
      $('body').css('font-variation-settings', computedStyle);
      setTimeout(function() {
        $('body').css('font-variation-settings', "'wght' 1");
      }, 500);
    }));
  });
});

JS解釋:

第一步:滾動時添加scrolling class。

第 2 步:添加一個setTimeout ,以便我們可以在用戶停止滾動時激活一個事件。 (我看到你已經有了這樣的東西,那太好了)。

第 3 步:當用戶停止滾動時,獲取當前font-variation-settings並將它們存儲為變量 ( computedStyle )。

第 4 步:刪除scrolling class 並將font-variation-settingscomputedStyle

第 5 步:等待 500 毫秒,以便過渡可以開始。 .5s后,我們重置 font font- variation-settings


帶有轉換的JSFiddle示例transform: rotate()

來源:這篇CSS-Tricks文章和這個Stack Overflow問題。

暫無
暫無

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

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