为不透明度和位置添加动画效果

Animate opacity and position

本文关键字:动画 添加 位置 不透明度      更新时间:2023-09-26

我在CodePen遇到了这支笔,我有几个问题。首先,让我们解释一下代码的作用:

input 事件中,有一个 forEach 循环,它遍历所有lis并检查匹配的正则表达式,然后相应地隐藏(或更准确地说,将opacity动画化为 0)li。然后,它有一个 while 循环(在 forEach 循环中),该循环再次遍历所有lis并将适当的translateY应用于lis(因为将 opacity 设置为 0 不会删除元素)。

问题

1 - 所以它出来了,如果你有 200 lis,它会迭代 (200 * 200 =) 40,000 次!我认为这不是很有效率。

2 - 另一个问题是,如果过滤掉一定数量的lis,滚动条仍然允许您向下滚动到那里的内容,因此向下滚动只会看到任何内容。在下面的示例中检查此问题。

前两个问题的明显解决方案是设置display: none而不是设置opacity: 0 。这样,您就不必重复所有lis 200 次,因为display: none会自动删除"空白"空间......正如您所猜测的,这也解决了第二个问题。

该解决方案的问题在于display: none不会动画。

如何在不遇到上述问题的情况下实现相同的动画?

代码笔

(由于字符限制,无法插入代码片段。这是相关的JavaScript代码:)

searchElem.addEventListener("input", function() {
    var rgx = new RegExp(this.value.replace(/([.^$|*+?()'[']{}''-])/g, "''$1"), 'i');
    searchArray.forEach(function(el, idx) {
        if (transitionEnd) {
            if (rgx.test(el)) cells[idx].removeAttribute('class');
            else cells[idx].className = 'hidden';
            var i = -1,
                cellPosition = 0;
            while (++i < cellLength) {
                if (cells[i].className != "hidden") 
                    cells[i].style.transform = "translateY(" + (cellPosition++ * cellHeight) + "px)";
            }
        }
    });
});

请不要j查询答案。

您可以通过避免li元素的绝对定位并转换li height及其opacity来避免滚动条问题和重复循环。

以下是我所做的:

  • li上删除了position: absolute,因为绝对定位意味着所有li都放在同一个点上,因此需要平移(translateY),以便它们一个接一个地显示。
  • li上增加了固定高度(height: 20px)。CSS 过渡不能将值转换为 auto/从 auto,因此我们需要为li提供一个固定的高度。我认为设置固定高度应该适合您的情况,因为它们看起来都像搜索结果,不会换行到多行。
  • 更改了transition设置以转换所有属性(或者也可以专门单独转换高度和不透明度),而不仅仅是不透明度和转换。
  • 修改了hidden类的 CSS 以包含 height: 0pxoverflow: hidden 。这意味着元素在隐藏时没有高度(溢出也被隐藏),因此避免了对translateY的需求(这是第二个循环所做的)和滚动条问题。
  • 除了删除额外的while循环外,不需要对 JS 进行任何更改。这是因为添加 hidden 类会自动产生淡入淡出和上移效果。
li {
  list-style-type: none;
  height: 20px; /* fixed height, set whatever is fit for your case */
  transition: all .5s ease-in-out;
}
.hidden {
  opacity: 0; /* produces the fade effect */
  height: 0px; /* transition height to 0px to produce move up effect */
  overflow: hidden; /* avoids the text from showing through when height is 0 */
}

CodePen 演示(由于字符限制,不会再次添加代码段)


在上面的代码(和演示)中,opacityheight同时转换,持续时间相同,因此opacity转换没有太多视觉效果。如果在height转换开始之前必须看到opacity更改,则向height转换添加延迟,如下面的代码所示:

li {
  list-style-type: none;
  height: 20px;
  transition: opacity .5s ease-in-out, height .5s ease-in-out .1s;
}

在原始代码段中,li项在加载时滑入它们的位置,如果您需要相同的效果,可以通过在开始时将class='hidden'设置为所有li然后使用 JS 删除类来生成它。

代码笔演示

@DarkFalcon您需要特定于浏览器的动画属性,例如:

     -webkit-animation: KEYFRAME-NAME 3s infinite;
}
@-webkit-keyframes KEYFRAME-NAME {
0%   { opacity: 0; }
50%  {opacity:.3;}
100% { opacity: 1; }