如何使用javascript动态设置css动画的关键帧?

zf9nrax1  于 2023-02-06  发布在  Java
关注(0)|答案(3)|浏览(260)

我想在我的产品页面上做一个动画。当用户点击"添加到购物车"的产品图像将是动画移动和缩小到导航栏中的购物车图标。这里是一个示例html

$('div.test').on('animationend', (e) => {
  $(e.target).remove();
})
//user click
$('div.test').addClass('animateTest');
.test {
  position   : fixed;
  top        : 200px;
  left       : 600px;
  background : red;
  width      : 200px;
  height     : 300px;
  }
@keyframes toCart {
  25% {
    top    : 850px;
    left   : 550px;
    width  : 200px;
    height : 300px;
    }
  100% {
    top    : 100px;
    left   : 1100px;
    width  : 0;
    height : 0
    }
  }
.animateTest {
  animation : toCart 2s;
  /* animation-fill-mode: forwards; */
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="test">

</div>

困难的部分是,由于用户的视区不同,我可能需要使用javascript来获得购物车图标的位置(除非我可以从CSS中获得它,我认为这是不可能的):

whereIsCart = $('#cartIcon').offset()

我需要做一些事情

100% {
    top    : whereIsCart.top;
    left   : whereIsCart.left;
    width  : 0;
    height : 0
  }

但是我该怎么做呢?或者,有没有更好的实践来达到同样的目标?

r6vfmomb

r6vfmomb1#

使用css过渡而不是关键帧动画可能更容易:

.test {
    // ...
    transition: transform 1s ease-in-out;
}
// on click
whereIsCart = $('#cartIcon').offset();
$('div.test').css('transform', 'translate(' + whereIsCart.left + 'px, ' + whereIsCart.top + 'px) scale(0)');
km0tfn4u

km0tfn4u2#

在JavaScript中使用CSS时,您可能希望使用CSSOM API;更具体地说,它是用于单位值的factory functions,例如CSS.px()CSS.percent()

    • 请注意**CSSOM API的某些部分仍处于试验阶段,例如工厂函数。在生产中,您应该确保目标浏览器支持您使用的功能。

不管动画本身使用CSS还是JS:要获取元素在视口中的当前位置,可以使用Element.getBoundingClientRect(),或者更一般地使用Element.getClientRects()来获取所有相关框。

CSS自定义属性

可以使用custom properties作为初始位置,也可以通过JavaScript进行设置,甚至可以在CSS中提供一个回退值。
如果您将它们用于动画(而不是作为动画)属性,则它应该可以正常工作:

const divTest = document.querySelector("div.test");
// Example for non-empty custom properties
divTest.style.setProperty("--top", CSS.px(20));
divTest.style.setProperty("--left", CSS.px(80));

// Should happen on click:
toCart(divTest);

function toCart(element) {
  const rect = element.getBoundingClientRect();

  element.style.setProperty("--top", CSS.px(rect.top));
  element.style.setProperty("--left", CSS.px(rect.left));
  element.classList.add("animateTest");
}
.test {
  position: fixed;
  top: var(--top, 10%);
  left: var(--left, 10%);
  width: 200px;
  height: 300px;
  background: red;
}
@keyframes toCart {
  25% {
    top: 80%;
    left: 50%;
    width: 200px;
    height: 300px;
  }
  100% {
    top: 10%;
    left: 100%;
    width: 0;
    height: 0;
  }
}
.animateTest {
  animation: toCart 2s;
}
<div class="test"></div>
    • 旁注**:如果你想使自定义属性本身具有动画效果,你必须在@property rule中定义,否则CSS无法使它具有动画效果,因为它的类型可以是任何类型(例如从长度到颜色的动画效果是不可能的)。

Web动画API

在JavaScript中,您可以使用Web Animations API,它本质上是CSS动画,但在JS中。
你可以定义关键帧,持续时间,填充模式等等。因为Animation.finished是一个承诺,你可以简单地通过awaitPromise.then()对动画的结束做出React。
示例:
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
使用Web动画也可以轻松完成多步动画,因为您可以在解决第一个动画的承诺后启动另一个动画。

mec1mxoz

mec1mxoz3#

CSS变量示例代码...

const
  bluElm = document.querySelector('#blue_elm')
, btAnim = document.querySelector('#bt-anim')
, btMovE = document.querySelector('#bt-movE')
, elTest = document.querySelector('.test')
  ;
btMovE.onclick = () =>
  { 
  bluElm.classList.toggle('move'); 
  }
btAnim.onclick = () =>
  {
  let rect = bluElm.getBoundingClientRect();

   /* change CSS variables values as style Property ------------- */
  elTest.style.setProperty('--p_top', `${rect.bottom}px`);
  elTest.style.setProperty('--p_left', `${rect.left}px`);

  elTest.classList.add('animateTest');
  }
elTest.onanimationend = () =>
  { 
  elTest.classList.remove('animateTest');
  }
#blue_elm {
  position : fixed;
  top      : 20px;
  left     : 300px;
  width         : 20px;
  height        : 20px;
  border-radius : 10px;
  background    : cornflowerblue;
  }
#blue_elm.move {
  top      : 50px;
  left     : 150px;
  } 
.test {
  position   : fixed;
  top        : 200px;
  left       : 600px;
  background : red;
  width      : 200px;
  height     : 300px;
  --p_top    : 0;       /* CSS variables  declaration */
  --p_left   : 0;
  }
.animateTest {
  animation : toCart 2s;
  }
@keyframes toCart {
  25% {
    top    : 850px;
    left   : 550px;
    width  : 200px;
    height : 300px;
    }
  100% {
    top    : var(--p_top);     /* CSS variables usage */
    left   : var(--p_left);
    width  : 0;
    height : 0
    }
  }
<button id="bt-anim"> show animation</button>

<button id="bt-movE"> move element +- 150px</button>

<div id="blue_elm"></div>

<div class="test"></div>

相关问题