如何立即删除css过渡?

时间:2017-03-21 15:01:05

标签: javascript jquery css css-transitions

我希望顺利转换css属性然后我想立即更改css属性值然后我想再次附加转换。为了更好地理解,请参阅以下示例:

if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
  $(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

setInterval(function() {
  
  $('.marquee-wrapper').css("transition", "none");
  $('.marquee-wrapper').css("transform", "translateY(100px)"); //This should Immediately change translateY to 100px without smooth transition. But this doesn't happen without adding a delay before the below written line
  
  // Its weird why javascript engine executes the below line before executing this line

  $('.marquee-wrapper').css("transition", "transform 3s linear");
  $('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

}, 3000);
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
}

.marquee-wrapper {
  transform: translateY(0);
}

.marquee-content {
  margin: 0;
  padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
  <div class="marquee-wrapper">
    <div class="marquee-content">
      Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
      loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
      = $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
      Similarly you can use pause the marquee any time using $mq.marquee('pause');.
    </div>
  </div>
</section>

正如您在setInterval中看到的,我首先将转换设置为none,然后将translateY转换为100px。现在原则上这应该突然将div转换为100px,但这不会发生在将div移动到100px之前javascript引擎执行下一行并重新分配转换。在下面的示例中,我在重新分配转换之前给出了100毫秒的延迟,它可以工作:

if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
  $(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

setInterval(function() {
  
  $('.marquee-wrapper').css("transition", "none");
  $('.marquee-wrapper').css("transform", "translateY(100px)"); //This  Immedeately change translateY to 100px without smooth transition now

  setTimeout(function(){
      $('.marquee-wrapper').css("transition", "transform 3s linear");
      $('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
  },100);
}, 3000);
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
}

.marquee-wrapper {
  transform: translateY(0);
}

.marquee-content {
  margin: 0;
  padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
  <div class="marquee-wrapper">
    <div class="marquee-content">
      Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
      loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
      = $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
      Similarly you can use pause the marquee any time using $mq.marquee('pause');.
    </div>
  </div>
</section>

我的问题是:

  1. 如何在更改translate属性之前阻止javscript引擎重新分配transition属性,没有任何延迟?
  2. 为什么javscript引擎会在当前行($('.marquee-wrapper').css("transition", "transform 3s linear");
  3. 之前的脚本中使用即将到来的行($('.marquee-wrapper').css("transform", "translateY(100px)");

3 个答案:

答案 0 :(得分:8)

transitiontransform CSS属性分组到一个语句中可以得到正确的结果,而不必使用100毫秒的延迟:

$('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
setInterval(function () {
    $('.marquee-wrapper').css({ transition: "none", transform: "translateY(100px)" });
    $('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
}, 3000);

if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
    $(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}

$('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });

setInterval(function () {
    $('.marquee-wrapper').css({ transition: "none", transform: "translateY(100px)" });
    $('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
}, 3000);
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
}

.marquee-wrapper {
  transform: translateY(0);
}

.marquee-content {
  margin: 0;
  padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
  <div class="marquee-wrapper">
    <div class="marquee-content">
      Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
      loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
      = $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
      Similarly you can use pause the marquee any time using $mq.marquee('pause');.
    </div>
  </div>
</section>

这种行为的原因可能是,设置两个CSS属性会立即触发立即重新绘制页面,而单独设置它们则不会。

已知某些Javascript命令会导致重绘。获取元素的offsetHeight是最经常提到的元素(参见this post)。事实上,它在this article中用于解决CSS转换问题,与此处介绍的问题非常类似。如果我们通过获取转换之间的元素高度来测试该方法,我们会发现结果行为确实是正确的:

$('.marquee-wrapper').css("transition", "none");
$('.marquee-wrapper').css("transform", "translateY(100px)");
$('.marquee-wrapper').height(); // Force a repaint
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
    $(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

setInterval(function () {
    $('.marquee-wrapper').css("transition", "none");
    $('.marquee-wrapper').css("transform", "translateY(100px)");
    $('.marquee-wrapper').height(); // Force a repaint
    $('.marquee-wrapper').css("transition", "transform 3s linear");
    $('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
}, 3000);
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
}

.marquee-wrapper {
  transform: translateY(0);
}

.marquee-content {
  margin: 0;
  padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
  <div class="marquee-wrapper">
    <div class="marquee-content">
      Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
      loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
      = $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
      Similarly you can use pause the marquee any time using $mq.marquee('pause');.
    </div>
  </div>
</section>

答案 1 :(得分:2)

我会解释你为什么会这样 我一直在处理javascript动画,并且有许多js库(专注于数学),考虑到操作延迟(I / O可用性策略)和超时。

在您的第一个代码段中,您有以下操作:

$('.marquee-wrapper').css("transform", "translateY(100px)");
$('.marquee-wrapper').css("transition", "transform 3s linear");

变换

Css变换方法使用具有高计算成本的基于矩阵的运算。有css动画框架使用图形处理器单元(具有矩阵运算符),其工作速度快几倍,以实现平滑,实时的图形操作。

过渡

Css Transition是另一种图形操作,但不会使用纯[matrix op matrix]转换修改css实体,它使用正确的1维运算符,这意味着您的css矩阵使用[matrix op array]进行修改

然后选择线性模式,在元素的位置上应用线性插值(可能只是几个积分运算符)。它具有较低的计算成本,这使得整个转换操作的计算速度更快。

这是在某种时间轴中执行的执行模式:

transform         calculation-process
exec -----------------------------------------> applied
 |         |                            |        |
 |         |                            |        |
 |         |                            |        |
transition |     calculation-process    |        |
--------- exec ---------------------> applied --------- 

由于javascript顶部的jQuery具有非阻塞代码执行(对于i / o依赖函数,除非你编码同步),这是javascript异步策略的基础,允许下一个操作甚至在执行之前执行先例完成。

具有超时功能的

您的修复确保在运行以下代码之前完成转换操作,但作为限制,对于具有类似计算速度的客户端,它将仅 比当前客户的处理器。 (如果你在个人电脑上开发它,那么它可能会在智能手机中失败)

我在代码中使用的另一个解决方案是使用jquery回调。看一下显示的jquery animate()doc

  

.animate(properties [,duration] [,easing] [,complete])

在您的示例中,它将类似于:

$('.marquee-wrapper').animate({"transform": "translateY(100px)"}, function(){
    // this code runs after transform ends...
    $('.marquee-wrapper').css("transition", "transform 3s linear");
    $('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
});

我找到了很多有用的库,可以“认真地”使用动画。这些是我使用的一些库:

d3.js
bounce.js
secuence.js
paper.js

我希望它有所帮助。

<强>更新
关于animate和css过渡有一个很好的答案here

答案 2 :(得分:0)

我认为这里有一些很好的答案告诉你它为什么会起作用,但如果你想要一个更多浏览器支持的动画,请使用jQuery animations

.append()

$wrap = $(".marquee-wrapper")
$con = $(".marquee-content");
cHeight = $con.outerHeight(true)

if ($(".marquee").height() < cHeight) {
  $con.clone().appendTo( $wrap );
}

function animate() {
  $wrap.animate({
    top: "-=" + cHeight
  }, 3000, "linear", function() { 
    $(this).css("top", "0");
    animate();
  });
}

animate();
//Cache values
$wrap = $(".marquee-wrapper")
$con = $(".marquee-content");
cHeight = $con.outerHeight(true)

if ($(".marquee").height() < cHeight) {
  $con.clone().appendTo( $wrap );
}


function animate() {
  $wrap.animate({
    top: "-=" + cHeight //minus height from the value of top
  },
  3000, // milisecs of animations length
  "linear", // type of animations
  function() { //function to run after animation is complete
    $(this).css("top", "0");
    animate();
  });
}

animate(); //Run function in the beginning
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
  position: relative;
}

.marquee-wrapper {  position: absolute;  }

.marquee-content {
  margin: 0;
  padding: 30px 0;
}

JSfiddle