анимация @keyframe на событии прокрутки - PullRequest
1 голос
/ 14 апреля 2020

Я использую переменный шрифт и хотел бы анимировать его с помощью @keyframes при прокрутке, а затем не анимировать, когда пользователь прекращает прокрутку.

Я могу заставить анимацию работать, однако, когда вы прекращаете прокрутку, анимация останавливается и возвращается в исходное положение, что делает ее очень нервной.

Чтобы сделать ее более плавной, sh, мне интересно, есть ли способ, когда пользователь прекращает прокрутку , можно получить текущую позицию анимации, а затем завершить эту анимацию l oop и затем остановиться, вместо того, чтобы сразу же вернуться к исходной позиции?

Поскольку я не могу загрузить переменный шрифт в jsfiddle, используя @ font-face, я поднял это здесь: 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;
}

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 17 апреля 2020

Ситуация, с которой вы сталкиваетесь, заключается в том, как просто перейти из любой точки анимации в положение c.
К сожалению, CSS не определено, поэтому мы должны прибегнуть к javascript к справиться с этим.

Основная идея c - запустить этот переход вручную. getComputedStyle может дать вам значение, при котором ваша анимация находится в данный момент, поэтому мы можем установить его для встроенного стиля нашего элемента, а затем удалить его сразу после принудительной перекомпоновки для перехода к исходным триггерам положения.

К сожалению, Safari ведет себя странно, и нам также приходится переключать свойство перехода, что заставляет эту операцию принудительно выполнять 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); }
}
click to toggle the animation on/off

С вашим кодом, который даст:

$(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;
}

(введите $(window).off('scroll') в вашем js консоль перед применением этих изменений, если вы sh попробуете это с веб-сайта OP).

0 голосов
/ 18 апреля 2020

Это должно сделать это.

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-direction: alternate; как а также animation-fill-mode: forwards;. Точно так же вы знаете.

JS:

$(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 Объяснение:

Шаг 1: Добавьте scrolling класс при прокрутке.

Шаг 2: Добавьте setTimeout, чтобы мы могли активировать событие, когда пользователь прекращает прокрутку. (Я видел, что у вас уже было что-то в этом роде, это здорово).

Шаг 3: Когда пользователь прекратит прокрутку, получите текущий font-variation-settings и сохраните их как переменную (computedStyle ).

Шаг 4: Удалить scrolling class и установить font-variation-settings в computedStyle.

Шаг 5: Подождите 500 мс, так переход может начаться. После .5s мы сбрасываем font- variation-settings.


Пример на JSFiddle с transform: rotate().

Источник: Это CSS -Трюки статья и этот Переполнение стека вопрос.

0 голосов
/ 18 апреля 2020

Мне не удалось получить доступ к вашему шрифту, поэтому вместо этого я использовал css свойство color!

Чтобы отслеживать конечную точку анимации, я использовал animationiteration событие на теле. Логика c:

Если анимация завершает «нечетное количество циклов», то измените color и animation-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-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>

Попробуй вживую! (за подробностями обращайтесь к консоли)


You возможно, мне интересно, почему я не использовал animationend непосредственно на body. Это связано с тем, что ваша анимация зацикливается бесконечно;)

...