尝试使用 JavaScript 触发 CSS 过渡



玩 JavaScript 和 CSS 过渡,我试图删除一个 CSS 类在动态插入div之后,使用JavaScript和innerHTML。

真的很惊讶地看到与蓝色div的不透明度相关的CSS过渡没有按照我想要的方式触发(在Safari下工作,在Chrome下随机工作,在Firefox Dev Edition下不起作用)。有人可以解释这种现象吗?

我不确定为什么它的工作方式与红色div 的工作方式不同。也许我不知道浏览器如何处理内部HTML?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Having fun with JS</title>
    <style>
        .std {
            width:100px;
            height:100px;
            opacity: 1;
            transition: opacity 5s;
        }
        .std--hidden {
            opacity: 0;
        }
        .std--red {
            background-color: red;
        }
        .std--blue {
            background-color: blue;
        }
    </style>
</head>
<body>
<button>click here</button>
<div class='std std--red std--hidden'></div>
<div class='insert-here'>
</div>
<script>
    // let a chance to the browser to trigger a rendering event before the class is toggled
    // see http://stackoverflow.com/a/4575011
    setTimeout(function() {
        // everything works fine for the red div
        document.querySelector('.std--red').classList.toggle('std--hidden');
    }, 0);

    document.querySelector('button').addEventListener('click', function(e) {
        var template = `<div class='std std--blue std--hidden'></div>`;
        document.querySelector('.insert-here').innerHTML = template;
        setTimeout(function() {
            // Why does the CSS transition seems to be triggered randomly ?
            // well more exactly
            // - it works under my Safari
            // - it does not work under my FirefoxDeveloperEdition
            // - it works randomly under my Google Chrome
            document.querySelector('.std--blue').classList.toggle('std--hidden');
        }, 0);
    });
</script>
</body>
</html>

编辑

所以我刚刚阅读了 CSS 过渡规范并发现了这个

对一组同时进行的样式更改的这种处理称为 样式更改事件。(实现通常具有样式更改 事件,以对应于他们所需的屏幕刷新率,以及何时 脚本需要最新的计算样式或布局信息 依赖于它的 API。

这可以以某种方式解释吗?setTimeout 0 在某些浏览器上是否太快,以至于它们没有时间计算样式差异,因此不会触发样式更改事件?事实上,如果使用更长的 setTimeout(例如,~16.6666,猜测 1/60 刷新率......),它似乎在任何地方都有效。有人可以确认吗?

我想我已经找到了答案,请参阅 CSS 3 过渡规范:

由于此规范未定义样式更改事件的时间 发生,因此考虑对计算值的更改 同时,作者应该意识到,更改任何 进行更改后一小段时间的转换属性 这种转变可能会导致行为在 实现,因为更改可能被视为同时在 一些实现,但不是其他实现。

我试图添加一点延迟,让浏览器注意到样式差异,并且它始终如一地工作。似乎某些浏览器执行 setTimeout 0 的速度确实比其他浏览器快:-)

    setTimeout(function() {
        document.querySelector('.std--blue').classList.toggle('std--hidden');
    }, 17);

要触发转换,您实际上不需要类来切换。这很重要,因为您可能无法动态设置类以事先切换。换句话说,您可能只需要更改一些CSS属性来触发转换。不过是的...您需要满足以下条件;

  1. 为了使 <div id="blue"></div> 元素进行动画处理,它必须携带定义transitionstd类。所以首先我们应该像blue.classList.add("std");
  2. 您需要异步执行任务。异步刷新 DOM 最好由 requestAnimationFrame() 函数完成。

var blue = document.getElementById("blue");
blue.classList.add("std");
blue.style.backgroundColor = "blue";
blue.style.opacity         = 0;
document.querySelector('button')
        .addEventListener( 'click'
                         , _ => requestAnimationFrame(_ => blue.style.opacity = 1)
                         );
.std { width:100px;
       height:100px;
       opacity: 1;
       transition: opacity 5s;
}
.std--red { background-color: red;}
<button>click here</button>
<div class='std std--red'></div>
<div id="blue"></div>

似乎您必须通过引用样式来触发过渡。我只是简单地添加了这一行(甚至添加到控制台.log也可以)

document.querySelector('.std.std--blue').style.width = '20';

在这里它的工作原理:JSFIDDLE

注意:我正在使用FirefoxDeveloperEdition。

我遵循了以下解决方案:

添加或删除类时,CSS 过渡不会进行动画处理,只会在更改 CSS 属性时进行动画处理。

完整脚本

<script>
setTimeout(function() {
    // everything works fine for the red div
    document.querySelector('.std--red').classList.toggle('std--hidden');
}, 0);

document.querySelector('button').addEventListener('click', function(e) {
    var template = `<div class='std std--blue std--hidden'></div>`;
    document.querySelector('.insert-here').innerHTML = template;
    document.querySelector('.std.std--blue').style.width = '20';
    setTimeout(function() {
        document.querySelector('.std.std--blue').style.width = '100';
        document.querySelector('.std--blue').classList.toggle('std--hidden');
    }, 0);
    });
</script>
您必须为

超时设置一个值,以便为元素插入 DOM 留出时间(在调用 document.querySelector 之前必须存在)

setTimeout(function() { document.querySelector('.std--blue').classList.toggle('std--hidden')},100);

您不需要第一次超时

onload = function() {
document.querySelector('.std--red').classList.toggle('std--hidden');
 document.querySelector('button').addEventListener('click', function(e) {
   var template = "<div class='std std--blue std--hidden'></div>";
   document.querySelector('.insert-here').innerHTML = template;
   setTimeout(function() { document.querySelector('.std--blue').classList.toggle('std--hidden')},100);
    });
}
 .std {
            width:100px;
            height:100px;
            opacity: 1;
            transition: opacity 5s;
        }
        .std--hidden {
            opacity: 0;
        }
        .std--red {
            background-color: red;
        }
        .std--blue {
            background-color: blue;
        }
<button>click here</button>
<div class='std std--red std--hidden'></div>
<div class='insert-here'>
</div>

相关内容

  • 没有找到相关文章