正如标题所暗示的那样,是否有正确的方法来设置一些初始的CSS属性(或类)并告诉浏览器将这些属性转换为另一个值?
例如(fiddle):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
st.transition = 'opacity 2s';
st.opacity = 1;
这不会为Chrome 29 / Firefox 23中元素的不透明度设置动画。这是因为(source):
[...]你会发现,如果你同时应用这两套属性, 在另一个之后,浏览器尝试优化该属性 更改,忽略您的初始属性并阻止转换。 在幕后,浏览器在绘制之前批量处理属性更改 虽然通常会加快渲染速度,但有时会产生不利影响 影响。
解决方案是在应用两组之间强制重绘 属性。这样做的一个简单方法就是访问DOM 元素的
offsetHeight
属性[...]
事实上,黑客确实可以在当前的Chrome / Firefox版本中运行。更新后的代码(fiddle - 打开小提琴后点击Run
再次运行动画):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
el.offsetHeight; //force a redraw
st.transition = 'opacity 2s';
st.opacity = 1;
然而,这是相当hackish,据报道在某些Android设备上不起作用。
另一个answer建议使用setTimeout
,以便浏览器有时间执行重绘,但也失败了,因为我们不知道重绘需要多长时间。猜测相当于毫秒数(30-100?)以确保重绘是否意味着牺牲性能,不必要地闲置,希望浏览器能够在那么短的时间内完成一些魔术。
通过测试,我发现了另一个使用requestAnimationFrame
(fiddle)在最新Chrome上运行良好的解决方案:
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
requestAnimationFrame(function() {
st.transition = 'opacity 2s';
st.opacity = 1;
});
我假设requestAnimationFrame
在执行回调之前等到下一次重绘开始之前,因此浏览器不会批量处理属性更改。这里不完全确定,但在Chrome 29上运行良好。
更新:经过进一步测试后,requestAnimationFrame
方法在Firefox 23上运行效果不佳 - 大部分时间似乎都失败了。 (fiddle)
是否有适当的或推荐的(跨浏览器)方式来实现这一目标?
答案 0 :(得分:11)
目前没有一种干净的方式(不使用CSS动画 - 请参阅the nearby answer by James Dinsdale以获取使用CSS动画的示例)。有一个spec bug 14617,遗憾的是自2011年提交以来没有采取行动。
setTimeout
在Firefox中无法正常运行(this is by design)。
我不确定requestAnimationFrame
- 原始问题的编辑说它也不能可靠地工作,但我没有调查。 (更新:看起来像requestAnimationFrame
is considered at least by one Firefox core developer to be the place where you can make more changes, not necessarily see the effect of the previous changes。)
强制重排(例如通过访问offsetHeight
)是一种可能的解决方案,但是对于转换工作,它应该足以强制重新设置(即getComputedStyle
):{{ 3}}
window.getComputedStyle(elem).opacity;
请注意,仅运行getComputedStyle(elem)
是不够的,因为它是懒惰计算的。我相信你从getComputedStyle询问哪个属性并不重要,restyle仍然会发生。请注意,询问与几何相关的属性可能会导致更昂贵的回流。
有关reflow / restyle / repaint的更多信息:https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/
答案 1 :(得分:5)
自2013年以来情况发生了变化,所以这是一个新答案:
您可以使用Web Animations。它们在Chrome 36和Firefox 40中原生实现,有a polyfill for all the other browsers。
示例代码:
var player = snowFlake.animate([
{transform: 'translate(' + snowLeft + 'px, -100%)'},
{transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();
答案 2 :(得分:2)
你不需要太多的JavaScript来实现你想要的东西,只需使用CSS关键帧和动画来达到同样的效果。
div {
opacity: 0;
}
div.fadeIn {
-webkit-animation: fadeIn 2s forwards;
animation: fadeIn 2s forwards;
}
@keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
@-webkit-keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
如this JsFiddle所示,它可以从页面加载(已添加类)或动态添加类来触发动画。
答案 3 :(得分:-1)
这是一个有效的版本。亲自看看。
在Chrome,Firefox,Opera上测试。
在我的firefox版本上,它不支持style.transition,因此如果标准名称不可用,我会使其回退到供应商特定名称。
var el = document.querySelector('div');
var VENDORS = ['Moz', 'Webkit', 'Ms', 'O'];
function getVendorSpecificName(el, prop) {
var style = el.style;
if (prop in style) {
return prop;
}
prop = ucfirst(prop);
for (var i = 0, l = VENDORS.length, name; i < l; i++) {
name = VENDORS[i] + prop;
if (name in style) {
return name;
}
}
return null;
}
function ucfirst(str) {
return str && str.charAt(0).toUpperCase() + str.substring(1);
}
function toCamelCase(str) {
return str.split('-').map(function (str, i) {
return i > 0 ? ucfirst(str) : str;
}).join('');
}
function animateCss(el, prop, from, to, duration) {
var style = el.style,
camel = toCamelCase(prop),
vendorSpecific = getVendorSpecificName(el, camel);
if (!vendorSpecific) {
console.log(prop + ' is not supported by this browser');
return false;
}
var transitionPropName = getVendorSpecificName(el, 'transition');
if (!(transitionPropName in style)) {
console.log('transition is not supported by this browser');
return false;
}
style[vendorSpecific] = from;
setTimeout(function () {
style[transitionPropName] = prop + ' ' + duration + 's ease';
setTimeout(function () {
style[vendorSpecific] = to;
}, 1);
}, 1);
return true;
}
animateCss(el, 'opacity', 0, 1, 2);
让我解释一下发生了什么:
制作了一些辅助函数,如ucfirst,toCamelCase
如果标准名称不可用,请尝试查找供应商特定的样式属性名称
利用setTimeout函数确保浏览器重绘
我尝试将其设为更通用的功能,以便也可以应用其他属性,例如颜色或背景。
希望这有帮助!
答案 4 :(得分:-1)
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('a.hiw*').click(function(){
id = this.id;
dval = $('#'+id).attr('data-value');
if (dval == 0) {
$('a.hiw*').attr('data-value','0');
$( ".hiw-popup" ).remove();
$('#'+id).attr('data-value','1');
$('<div class="hiw-popup white-well run-animation hidden-xs"><div class="row text-center"><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-pencil hiw-icon1" style="background:#ffffff;">1</span><br/>block1</div><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-shopping-cart hiw-icon2">2</span><br/>BLOCK3</div><div class="col-sm-3 animation-hiw col-xs-3"><span class="glyphicon glyphicon-folder-open hiw-icon3">3</span><br/>BLOCK2</div><div class="col-sm-3 animation-hiw col-xs-3"><span class="glyphicon glyphicon-ok hiw-icon4">4</span><br/>BLOCK</div><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-arrow-down hiw-icon5">5</span><br/>BLOCK</div></div></div>').insertAfter('#'+id);
}else{
$('#'+id).attr('data-value','0');
$( ".hiw-popup" ).remove();
}
});
});
var ahiw = function(id){
dval = $('#'+id).attr('data-value');
if (dval == 0) {
$('a.hiw*').attr('data-value','0');
$( ".hiw-popup" ).remove();
$('#'+id).attr('data-value','1');
$('<div class="hiw-popup white-well run-animation hidden-xs"><div class="row text-center"><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-pencil hiw-icon1" style="background:#ffffff;">1</span><br/>block1</div><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-shopping-cart hiw-icon2">2</span><br/>BLOCK3</div><div class="col-sm-3 animation-hiw col-xs-3"><span class="glyphicon glyphicon-folder-open hiw-icon3">3</span><br/>BLOCK2</div><div class="col-sm-3 animation-hiw col-xs-3"><span class="glyphicon glyphicon-ok hiw-icon4">4</span><br/>BLOCK</div><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-arrow-down hiw-icon5">5</span><br/>BLOCK</div></div></div>').insertAfter('#'+id);
}else{
$('#'+id).attr('data-value','0');
$( ".hiw-popup" ).remove();
}
}
</script>
&#13;
/* Chrome, Safari, Opera */
@-webkit-keyframes animation-hiw-icon {
from {
background-color: #d9d9d9;
}
to {
background-color: #4ad18f;
}
}
/* Standard syntax */
@keyframes animation-hiw-icon {
from {
background-color: #d9d9d9;
}
to {
background-color: #4ad18f;
}
}
/* Chrome, Safari, Opera */
@-webkit-keyframes animation-hiw-prog {
from {
background-color: #d9d9d9;
width: 0%
}
to {
width: 100%;
background-color: #4ad18f;
}
}
/* Standard syntax */
@keyframes animation-hiw-prog {
from {
width: 0%
}
to {
width: 100%;
}
}
/* Chrome, Safari, Opera */
@-webkit-keyframes animation-hiw-pop {
from {
opacity: 0.5;
background-color: #d9d9d9;
-ms-transform: scale(0.8); /* IE 9 */
-webkit-transform: scale(0.8); /* Chrome, Safari, Opera */
transform: scale(0.8);
}
to {
background-color: #4ad18f;
opacity: 1;
font-weight: normal;
-ms-transform: scale(.8); /* IE 9 */
-webkit-transform: scale(.8); /* Chrome, Safari, Opera */
transform: scale(.8);
}
}
/* Standard syntax */
@keyframes animation-hiw-pop {
from {
background-color: #d9d9d9;
opacity: 0.5;
-ms-transform: scale(0.8); /* IE 9 */
-webkit-transform: scale(0.8); /* Chrome, Safari, Opera */
transform: scale(0.8);
}
to {
background-color: #4ad18f;
opacity: 1;
font-weight: normal;
-ms-transform: scale(.8); /* IE 9 */
-webkit-transform: scale(.8); /* Chrome, Safari, Opera */
transform: scale(.8);
}
}
/*Animation Trigger*/
.run-animation .hiw-progress:after, .run-animation .animation-hiw, .run-animation .hiw-icon1, .run-animation .hiw-icon2, .run-animation .hiw-icon3, .run-animation .hiw-icon4, .run-animation .hiw-icon5 {
-webkit-animation-play-state: running; /* Safari and Chrome */
animation-play-state: running;
}
.run-animation .hiw-progress:after, .run-animation .animation-hiw, .run-animation .hiw-icon1, .run-animation .hiw-icon2, .run-animation .hiw-icon3, .run-animation .hiw-icon4, .run-animation .hiw-icon5 {
-webkit-animation-play-state: running;
animation-play-state: running;
}
.hiw-progress:after {
content: "";
width: 0%;
height: 5px;
background: #4ad18f;
display: inline-block;
position: absolute;
top: 0;
left: 0;
-webkit-animation: animation-hiw-prog 5s linear forwards;
animation: animation-hiw-prog 5s linear forwards;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.white-well {
background-color: #fff;
padding: 10px 15px; border-radius: 5px;
border: 1px solid #f1f1f1;
}
.hiw-popup {
position: absolute;
width: 100%;
z-index: 9;
margin: 30px 0 0 -15px;
padding: 0px 15px !important;
border-color: rgba(0, 0, 0, 0.25) !important;
box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.60);
-webkit-box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.60);
-mz-box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.60);
}
.hiw-popup .arrow {
position: absolute;
display: block;
width: 0;
height: 0; border-color: transparent;
border-style: solid;
border-width: 11px;
left:90%;
margin-left: -11px;
border-top-width: 0;
border-bottom-color: rgba(0, 0, 0, 0.25);
top: -11px;
}
.hiw-popup .glyphicon {
margin-bottom: 10px;
margin-right: 0px !important;font-weight:bold;
background-color: #ffffff;color:#222222 !important;
}
.white-well .glyphicon {
background-color: #ffffff!important;
border-radius: 76px;margin-top: -3px;color:#d9d9d9 !important;
padding: 5px 9px 8px;
color: #fff;
box-shadow: 0px 0px 3px #222222;
border: 3px solid #ffffff;
}
.glyphicon {
position: relative;
top: 1px;
display: inline-block;
font-family: 'Glyphicons Halflings';
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.clearfix:before, .clearfix:after, .container:before, .container:after, .container-fluid:before, .container-fluid:after, .row:before, .row:after, .form-horizontal .form-group:before, .form-horizontal .form-group:after, .btn-toolbar:before, .btn-toolbar:after, .btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after, .nav:before, .nav:after, .navbar:before, .navbar:after, .navbar-header:before, .navbar-header:after, .navbar-collapse:before, .navbar-collapse:after, .modal-footer:before, .modal-footer:after, .review:before, .review:after, .panel-body:before, .panel-body:after {
content: " ";
display: table;
}
.animation-hiw:nth-child(1) {
-webkit-animation-delay: .2s;
animation-delay: .2s;
}
.hiw-icon5 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: 5s;
animation-delay: 5s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.hiw-icon4 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: 3.75s;
animation-delay: 3.75s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.hiw-icon3 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: 2.25s;
animation-delay: 2.25s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.hiw-icon2 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: 1s;
animation-delay: 1s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.hiw-icon1 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: .2s;
animation-delay: .2s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.animation-hiw {
-webkit-animation: animation-hiw-pop 0.2s forwards; /* Chrome, Safari, Opera */
animation: animation-hiw-pop 0.2s forwards;
-webkit-animation-play-state: paused; /* Safari and Chrome */
animation-play-state: paused;
opacity: 0.5;
-ms-transform: scale(0.8); /* IE 9 */
-webkit-transform: scale(0.8); /* Chrome, Safari, Opera */
transform: scale(0.8);
background: #d9d9d9;
width: 15%;
padding: 2% 1%;
height: 140px;
color: #ffffff; float: left;
}
.animation-hiw:nth-child(1){ -webkit-animation-delay: .2s; animation-delay: .2s; }
.animation-hiw:nth-child(2){ -webkit-animation-delay: 1s; animation-delay: 1s; }
.animation-hiw:nth-child(3){ -webkit-animation-delay: 2.25s; animation-delay: 2.25s; }
.animation-hiw:nth-child(4){ -webkit-animation-delay: 3.75s; animation-delay: 3.75s; }
.animation-hiw:nth-child(5){ -webkit-animation-delay: 5s; animation-delay: 5s; }
hiw {
visibility: hidden;
font-size: 12px;
font-style: italic;
text-align: right;
float: right;
}
&#13;
<body>
<a href="javascript:void(0);" class="hiw hidden-xs" id="hiw_1" data-value="1" style="float:LEFT;margin-right:10px;color: #4ad18f;font-size: 12px;padding:0px 0px 5px 0px;">How it works</a>
</body>
&#13;