正如标题所示,是否有适当的方法来设置一些初始CSS属性(或类)并告诉浏览器将其转换为另一个值?
例如(fiddle):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
st.transition = 'opacity 2s';
st.opacity = 1;
这将不会在Chrome 29/FFirefox 23中设置元素不透明度的动画。这是因为(来源):
[…]你会发现,如果你同时应用这两组属性,就会立即应用一组然后,浏览器尝试优化属性更改,忽略初始属性并阻止转换。在幕后,浏览器在绘制之前会批量处理属性更改这通常会加快渲染速度,但有时会产生不利影响影响。
解决方案是在应用两组属性。一个简单的方法就是访问DOM元素的
offsetHeight
属性〔…〕
事实上,黑客攻击在当前的Chrome/Firefox版本中确实有效。更新代码(fiddle-打开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;
然而,这是相当黑客,据报道在一些安卓设备上不起作用。
另一个答案建议使用setTimeout
,这样浏览器就有时间执行重绘,但它也失败了,因为我们不知道重绘需要多长时间。猜测一个适当的毫秒数(30-100?)以确保重新绘制发生意味着牺牲性能,不必要地空转,希望浏览器在这段时间内发挥一些魔力。
通过测试,我发现了另一个在最新Chrome上运行良好的解决方案,使用requestAnimationFrame
(fiddle):
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上运行得不太好——它似乎在大多数时候都失败了。(小提琴)
是否有适当的或推荐的(跨浏览器)方式来实现这一点?
目前没有一种干净的方法(不使用CSS动画——请参阅James Dinsdale的回答,了解使用CSS动画的示例)。有一个规范错误14617,不幸的是,自2011年提交以来,该错误一直没有得到执行。
setTimeout
在Firefox中不能可靠地工作(这是故意的)。
我不确定requestAnimationFrame
——对原始问题的编辑表明它也不可靠,但我没有进行调查。(更新:至少有一位Firefox核心开发人员认为requestAnimationFrame
是可以进行更多更改的地方,而不一定能看到以前更改的效果。)
强制回流(例如通过访问offsetHeight
)是一种可能的解决方案,但为了使转换工作,它应该足以强制重新样式(即getComputedStyle
):https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/
window.getComputedStyle(elem).opacity;
请注意,仅仅运行getComputedStyle(elem)
是不够的,因为它是延迟计算的。我相信无论你从getComputedStyle中请求哪个属性,restyle仍然会发生。请注意,要求几何图形相关的属性可能会导致更昂贵的回流。
有关回流/重新造型/重新喷漆的更多信息:http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/
自2013年以来,情况发生了变化,因此有一个新的答案:
您可以使用Web动画。它们在Chrome 36和Firefox 40中原生实现,并且所有其他浏览器都有polyfill。
示例代码:
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();
您不需要太多的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;}
}
如JsFiddle所示,它可以在页面加载(已经添加了类)时工作,也可以在动态添加类以触发动画时工作。
-
<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>
/* 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; }
<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>
#
这是一个工作版本。你自己看看。
在Chrome、Firefox、Opera上测试。
在我的firefox版本中,它不支持style.transition,所以如果标准名称不可用,我会回退到供应商特定的名称。
http://jsfiddle.net/eNCBz/5/
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
- style属性使用大小写名称
如果标准名称不可用,请尝试查找供应商特定的样式属性名称
利用setTimeout功能确保浏览器重新绘制
- 据我所知,所有浏览器总是在超时时重新绘制
我试着让它更通用,这样其他属性也可以应用,比如颜色或背景。
希望这能有所帮助!