删除上面的元素后,CSS3将元素动画或过渡到位置

时间:2017-06-16 14:29:21

标签: css css3 animation css-animations

在没有任何明显的闪烁和任何奇怪的情况下实现这一目标的最佳方法是什么?

开始的小提琴:http://jsfiddle.net/35qec14b/2/



$('.element').on('click', function(e){
  this.remove();
});

.element {
  position:relative;
  width: 200px;
  margin:5px;
  padding:20px;
  cursor:pointer;
  background: rgb(150,200,250);
  transition:1s linear;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
(click to remove)
<div class="element">Element 1</div>
<div class="element">Element 2<br>Second line</div>
<div class="element">Element 3</div>
<div class="element">Element 4<br>Second line</div>
<div class="element">Element 5</div>
&#13;
&#13;
&#13;

注意:在这种情况下,删除的元素必须立即消失,因为它会出现在另一个位置,我们不希望它同时在两个地方可见。

到目前为止的想法:

  • 转换:translateY 以查找已移除的元素下方的所有元素(可能是大型列表的性能密集型)
  • 动画/转换下面第一个元素的边距,从移除元素的高度到0(利用链式动画?步骤开始?)
  • 使用透明占位符替换已删除的元素,并将其自身的高度设置为0

3 个答案:

答案 0 :(得分:6)

最好的想法是隐藏它,克隆它的新位置(这里没有显示),然后设置它的高度动画

当为一个边距,填充和高度设置动画时,它变得不那么平滑,所以我为内容添加了一个额外的内部包装器,因此动画只能动画高度

non-www
$('.element').on('click', function(e) {
  this.style.height = $(this).height()+ 'px';
  this.classList.add('hide-me');
  (function(el) {
    setTimeout(function() {
      el.remove();
    }, 500);
  })(this);
});
.element {
  position: relative;
  width: 200px;
  overflow: hidden;
}
.element > div {
  margin: 5px;
  padding: 20px;
  background: rgb(150, 200, 250);
}

.element.hide-me {
  animation: hideme .5s forwards;
  opacity: 0;
}
@keyframes hideme {
  100% {
    height: 0;
  }
}

答案 1 :(得分:0)

这是使用.animate()

的jQuery方法

$('.element').on('click', function(e){
  var $this = $(this), $next = $this.next();
  $next.css({
    marginTop: $this.outerHeight(true)
  }).animate({
    marginTop: 5
  }, 200);
  $this.remove();
});
.element {
  position:relative;
  width: 200px;
  margin:5px;
  padding:20px;
  cursor:pointer;
  background: rgb(150,200,250);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
(click to remove)
<div class="element">Element 1</div>
<div class="element">Element 2<br>Second line</div>
<div class="element">Element 3</div>
<div class="element">Element 4<br>Second line</div>
<div class="element">Element 5</div>

这是一个CSS过渡方法

$('.element').on('click', function(e){
  var $this = $(this), $next = $this.next();
  $next.css({
    marginTop: $this.outerHeight(true)
  });
  setTimeout(()=>{
    $next.addClass('hide');
    setTimeout(()=>{
      $next.css({marginTop: ''}).removeClass('hide');
    }, 250)
  }, 20);
  $this.remove();
});
.element {
  position:relative;
  width: 200px;
  margin:5px;
  padding:20px;
  cursor:pointer;
  background: rgb(150,200,250);
}

.element.hide {
  transition: margin-top 0.25s linear;
  margin-top: 5px !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
(click to remove)
<div class="element">Element 1</div>
<div class="element">Element 2<br>Second line</div>
<div class="element">Element 3</div>
<div class="element">Element 4<br>Second line</div>
<div class="element">Element 5</div>

答案 2 :(得分:0)

即使您担心使用转换可能会产生负面影响,但我认为情况正好相反。

请记住,其他解决方案涉及大量回流,这可能会对CPU造成更大的性能影响(转换很可能是由GPU处理的)。

然而,使用变换解决这个问题有点难以编码。特意更改需要移动的像素数量,并将它们注入样式。

查看可行的解决方案。我只使用JS来使它更便携。

如果您关注性能,可以将findKeyframesRule的结果分配给变量并重复使用。

&#13;
&#13;
document.addEventListener('DOMContentLoaded', setEvent, false);

function setEvent() {
  var elements = document.getElementsByClassName('element');

  for (var n = 0; n < elements.length; n++) {
    elements[n].addEventListener('click', remove, false);
  }
}

function remove(event) {
  var current = event.currentTarget;
  var elements = document.getElementsByClassName('move');
  for (var n = 0; n < elements.length; n++) {
    elements[n].classList.remove('move');
  }
  window.setTimeout(function() {
    remove2(current);
  }, 0);
}

function remove2(current) {
  var next = current.nextElementSibling;
  if (!next) {
    return;
  }
  var top1 = current.offsetTop;
  var top2 = next.offsetTop;
  var diff = top2 - top1;
  var newTransform = 'translateY(' + diff + 'px)';

  var rule = findKeyframesRule('move');
  var style = rule.cssRules[0].style;
  style.transform = newTransform;
  next.classList.add('move');
  current.style.height = '0px';
}

function findKeyframesRule(rule) {
  // gather all stylesheets into an array
  var ss = document.styleSheets;

  // loop through the stylesheets
  for (var i = 0; i < ss.length; i++) {

    var ss1 = ss[i];
    // loop through all the rules
    if (!ss1.cssRules) {
      alert('you are using Chrome in local files');
      return null;
    }
    for (var j = 0; j < ss1.cssRules.length; j++) {

      // find the keyframe rule whose name matches our passed parameter
      if (ss1.cssRules[j].type == window.CSSRule.KEYFRAMES_RULE && ss1.cssRules[j].name == rule)
        return ss1.cssRules[j];
    }
  }
  return null;
}
&#13;
.element {
  position: relative;
  width: 200px;
  overflow: hidden;
}

.element>div {
  margin: 5px;
  padding: 20px;
  background: rgb(150, 200, 250);
}

.move,
.move~.element {
  animation: move 2s;
}

@keyframes move {
  from {
    transform: translateY(60px);
  }
  to {
    transform: translateY( 0px);
  }
}
&#13;
(click to remove)
<div class="element">
  <div>
    Element 1
  </div>
</div>
<div class="element">
  <div>
    Element 2
    <br>Second line
  </div>
</div>
<div class="element">
  <div>
    Element 3
  </div>
</div>
<div class="element">
  <div>
    Element 4
    <br>Second line
  </div>
</div>
<div class="element">
  <div>
    Element 5
  </div>
</div>
&#13;
&#13;
&#13;