最近作了一个导航条动画,鼠标hover的时候会有一个可移动的下划线,html结构大体以下css
<div class="nav-sliderbar fl rel"> <ul class="clearfix"> <li class=""><a href="/b/AAA">AAA</a></li> <li class=""><a href="/b/BBB">BBB</a></li> <li class=""><a href="/b/CCC">CCC</a></li> <li class=""><a href="/b/DDD">DDDD</a></li> </ul> <span class="slider-underline"></span> </div>
slider-underline使用了transition样式:html
.slider-underline { position: absolute; border-width: 1px 0; border-style: solid; border-color: #444; height: 0px; bottom: 12px; width: 26px; left : -26px; -webkit-transition: left 0.2s cubic-bezier(0.16, 0.71, 0.46, 1.43); -moz-transition: left 0.2s cubic-bezier(0.16, 0.71, 0.46, 1.43); -o-transition: left 0.2s cubic-bezier(0.16, 0.71, 0.46, 1.43); transition: left 0.2s cubic-bezier(0.16, 0.71, 0.46, 1.43); }
在页面生成的时候根据板块不一样须要初始化slider-underline的位置。web
var underline_width = $('.slider-underline').width(); var active_position = $('.nav-sliderbar .actived').length ? $('.nav-sliderbar .actived').width()/2 + $('.nav-sliderbar .actived').position().left - underline_width/2 : - underline_width; //上面两句是计算的导航条滑块的初始的位置,正好在激活的板块对应位置的下方。 $('.slider-underline').css('left', active_position+'px');
因为slider-underline默认有transition,所以在页面刷新初始化其left位置的时候就会触发动画效果。这个体验不是很好,但愿能在初始化的时候不触发这个动画,所以考虑了将动画效果作成一个类:浏览器
.underline-bezier { -webkit-transition: left 0.2s cubic-bezier(0.16, 0.71, 0.46, 1.43); -moz-transition: left 0.2s cubic-bezier(0.16, 0.71, 0.46, 1.43); -o-transition: left 0.2s cubic-bezier(0.16, 0.71, 0.46, 1.43); transition: left 0.2s cubic-bezier(0.16, 0.71, 0.46, 1.43); }
js底下添加:ide
$('.slider-underline').css('left', active_position+'px'); $('.slider-underline').addClass('underline-bezier');
然而此处出现了问题,这么作了页面效果并无变化。
按理说修改left会致使页面的重绘和回流,可是实际上却没有达到预想的效果。函数
翻阅一些资料后,我的得出的结论是,浏览器为了减小重绘的次数,会维护一个flush队列,当有须要重排的时候将操做放入队列,队列满时再一次性重绘。因此上面这两句被浏览器合并到一块儿写入了。动画
鉴于这个缘由,我尝试出了两种解决办法:spa
使用setTimeoutcode
setTimeout(function() { $('.slider-underline').addClass('underline-bezier'); },0);
这个方法已开始写的时候只是尝试性的,可是达到了须要的效果,具体缘由到底是由于浏览器任务插入的问题仍是由于执行其中函数前flush队列已满触发了重绘,还真正没有搞清楚。htm
强制提早flush队列
当获取如下属性的时候,浏览器为了获取准确的位置会强制浏览器提早flush队列。
offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop/Left/Width/Height
clientTop/Left/Width/Height
width,height
getComputedStyle() / currentStyle
所以将js改成:
$('.slider-underline').css('left', active_position+'px'); var get_left = $('.slider-underline').css('left'); $('.slider-underline').addClass('underline-bezier');
就能达到预想的效果了。