在奇数位置设置动画时,在Chrome中抖动图像

时间:2013-01-11 16:43:50

标签: javascript jquery css google-chrome jquery-animate

我试图创建某种屏蔽动画,从中心显示图像(编辑:"中心"并不一定意味着实际背景图像的中心,但可见区域的中心! / edit )。它到目前为止工作正常,唯一的问题是在Chrome中(目前在Windows 7 x64上为24.0.1312.52米)显示的内容正在震动。

以下是一个例子:http://jsfiddle.net/BaKTN/

到目前为止,我发现可以通过不禁用background-repeathttp://jsfiddle.net/BaKTN/1/)来解决此问题。不确定内部究竟发生了什么,但这使得图像保持在它所属的位置。不幸的是,只有问题的一半,当外部容器放置在奇数坐标上时再次发生抖动,例如,当使用基于百分比的定位时(例如,在内部,坐标可能是奇数),可能会发生这种情况。

这是另一个显示此行为的jsfiddle示例:http://jsfiddle.net/VbgXB/

编辑使用固定定位似乎有所帮助,即使使用更多的外部容器会导致奇数坐标,一切看起来都很好。然而,这种解决方法仅在条件上有用,因为它会弄乱滚动:http://jsfiddle.net/BaKTN/5/。所以我还在寻找另一种技巧。的 /修改

任何想法是什么导致了这个问题以及如何在不改变容器坐标的情况下绕过它?这可能与此错误有关:http://code.google.com/p/chromium/issues/detail?id=140038

PS。请注意,这是成为更大的动画(多个瓷砖)的一部分,需要保持CSS2兼容!

1 个答案:

答案 0 :(得分:5)

这可能是由于背景位置的部分像素值造成的。舍入值似乎可以解决它:http://jsfiddle.net/BaKTN/2/

(function($) {
  $.extend($.fx.step,{
    backgroundPosition: function(fx) {
      if (typeof fx.end == 'string') {
        var start = $.css(fx.elem,'backgroundPosition');
        start = toArray(start);
        fx.start = [start[0],start[2]];
        var end = toArray(fx.end);
        fx.end = [end[0],end[2]];
        fx.unit = [end[1],end[3]];
      }
      var nowPosX = [];

相关代码

      nowPosX[0] = Math.round(((fx.end[0] - fx.start[0]) * fx.pos) + fx.start[0]) + fx.unit[0];
      nowPosX[1] = Math.round(((fx.end[1] - fx.start[1]) * fx.pos) + fx.start[1]) + fx.unit[1];

结束相关代码

      fx.elem.style.backgroundPosition = nowPosX[0]+' '+nowPosX[1];

      function toArray(strg){
        strg = strg.replace(/left|top/g,'0px');
        strg = strg.replace(/right|bottom/g,'100%');
        strg = strg.replace(/([0-9\.]+)(\s|\)|$)/g,"$1px$2");
        var res = strg.match(/(-?[0-9\.]+)(px|\%|em|pt)\s(-?[0-9\.]+)(px|\%|em|pt)/);
        return [parseFloat(res[1],10),res[2],parseFloat(res[3],10),res[4]];
      }
    }
  });
})(jQuery);

修改 - 将#container位置转换为(整数)像素而非百分比将修复第二种情况,但在调整窗口大小时不会调整其位置:{{ 3}}

var $con = $("#container");
$con.css({
  left: Math.round($con.position().left),
  top: Math.round($con.position().top)
});