检测由 CSS 过渡引起的 HTML 元素的移动

Posted

技术标签:

【中文标题】检测由 CSS 过渡引起的 HTML 元素的移动【英文标题】:Detect movement of HTML element caused by CSS transitions 【发布时间】:2013-04-06 00:30:21 【问题描述】:

我的页面上有一个 Flash 元素,由于 Flash 通常非常精细,因此需要将其定位在整数像素值处(如果需要详细信息,请参阅 Flash webcam access request prompt unresponsive)。

我通过将object 包装在div 中、在object 上设置position:absolute 并使用jQuery 将lefttop 设置为圆角的offset 来实现这一点包含div。那是一口,这里是代码形式:

<div id="wrapper">
    <object id="flash" blah style="position:absolute">
        <!-- blah -->
    </object>
</div>
<script>
    function update()
        var p=$('#wrapper').offset();
        $('#flash').css('left':Math.round(p.left),'top':Math.round(p.top));
    
    $(document).ready(function()
        $(window).resize(update);
        update();
    );
</script>

而且一切都很好(如果上面的代码有错误,那只是将其删减)

这将在浏览器改变大小时更新位置,当位置被一些 javascript 改变时更新它很容易,但是页面也使用 CSS transition-duration 来动画一些变化。我怎样才能检测到这个?至少,我想检测影响对象的过渡何时发生,并知道它何时停止。理想情况下,我想知道如何捕捉任何运动(例如由字体大小更改或图像加载引起的)。

【问题讨论】:

有一些关于过渡的事件,但我不知道它们有多大用处 您可以检测到过渡何时完成,但仍无法检测到过渡何时开始,至少我不知道。搜索 transitionend 事件 @roasted 谢谢,这是一个开始。它至少现在最终定位正确。如果可能的话,我仍然想在动画期间定位它。致未来的读者:.on('transitionend webkitTransitionEnd oTransitionEnd otransitionend',update); 所以我想没有一个理想的解决方案。也许,在制作动画之前,您可以使用 JS 来检测是否设置了 CSS 过渡。而且我不知道这是否适用于您的情况,但也许最好使用 translate 移动元素; Paul Irish wrote a good article about this. @sroes translate 不适用,遗憾的是。这样做的重点是删除子像素定位,但 translate 支持子像素并且不够聪明,无法采用方程参数(我需要通过 floor(absolute_coord) - absolute_coord 进行翻译)。 【参考方案1】:

你能检查一下这个小提琴吗:http://jsfiddle.net/DpYNm/ 它会记录运动的开始和结束时间,我不确定它是否能解决您的问题,但它可能会帮助您朝着正确的方向前进!

function checkForMove() 
if ($('#testDiv').prop('user_default_width') === undefined) 
    $('#testDiv').prop('user_default_width', $('#testDiv').width());
    $('#testDiv').prop('user_is_moving', false);


if ($('#testDiv').width() != $('#testDiv').prop('user_default_width') && !$('#testDiv').prop('user_is_moving')) 
    $('#log').html($('#log').html() + "Move started<br/>");
    $('#testDiv').prop('user_is_moving', true);

if ($('#testDiv').width() == $('#testDiv').prop('user_default_width') && $('#testDiv').prop('user_is_moving')) 
    $('#log').html($('#log').html() + "Move ended<br/>");
    $('#testDiv').prop('user_is_moving', false);


setTimeout(checkForMove, 1);

checkForMove();

checkForMove 每毫秒调用一次,在第一次调用中,它将 div 的宽度保存到一个属性中。每次它发生变化(转换开始)时,它都会记录并保存一个辅助属性,以确保在转换恢复到默认大小之前不会再次记录。我相信您可以更改该部分以适合您的需求! :)

【讨论】:

每毫秒?!冷酷的!无论如何,我知道我可以使用间隔(你应该使用 setInterval 而不是 setTimeout 来处理这样的事情;超时很浪费),但我正在寻找一个事件驱动的解决方案。 我认为没有事件驱动的解决方案。但是,您可以增加超时时间,尽管 1 毫秒对于 cpu 来说是很多时间,即使在 javascript 中也是如此。关于 setTimeout 和 setInterval 之间的区别:它们本质上是相同的,但是 setInterval 将每 x 毫秒执行一次,而我使用 setTimeout 的方式意味着只有在超时中的代码执行完毕后,计时器才会重新启动。 Afaik 他们在内部使用相同的机制。

以上是关于检测由 CSS 过渡引起的 HTML 元素的移动的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 iOS 上由 CSS 过渡和变换引起的闪烁?

CSS过渡效果

将元素从当前位置过渡到视口中心?

过渡和变换之前的 CSS 位置元素

CSS变化过渡与动画

触摸移动触发时css过渡不一致