【问题标题】:Why is transition on 'transform: scale()' makes an element become pixelated in webkit browsers?为什么'transform:scale()'上的转换会使元素在webkit浏览器中变得像素化?
【发布时间】:2014-10-24 18:23:34
【问题描述】:

如果我使用 CSS scale() 缩放元素,它在过渡时会变得像素化。但过渡完成后又恢复正常(参考截图 1)。但是它只发生在 webkit 浏览器中(在 Chrome 和 Opera 中测试过)

.foo {
  background: #4FC093;
  display: block;
  position: absolute;
  width: 20px;
  height: 20px;
  box-shadow: 0 0 10px inset;
  margin: 0 auto;
  border-radius: 50%;
  left: 50%;
  top: 50%;
  cursor: pointer;
  -webkit-transition: all 3s ease;
  -moz-transition: all 3s ease;
  -ms-transition: all 3s ease;
  transition: all 3s ease;
}

.foo:hover {
  -webkit-transform: scale(20);
  -moz-transform: scale(20);
  -ms-transform: scale(20);
  transform: scale(20);
}
<div class="foo"></div>

截图 1

一种可能的解决方法

我也尝试过使用scale3d() 来反转这个div 的比例,正如here 所建议的那样
但它在 Google Chrome 中导致 div 周围出现锯齿状边缘。

.foo {
  background: #4FC093;
  display: block;
  position: absolute;
  width: 400px;
  height: 400px;
  box-shadow: 0 0 200px inset;
  margin: 0 auto;
  border-radius: 50%;
  cursor: pointer;
  -webkit-transition: all 3s ease;
  -moz-transition: all 3s ease;
  -ms-transition: all 3s ease;
  transition: all 3s ease;
  -webkit-transform: scale3d(0.05, 0.05, 0.05);
  -moz-transform: scale3d(0.05, 0.05, 0.05);
  -ms-transform: scale3d(0.05, 0.05, 0.05);
  transform: scale3d(0.05, 0.05, 0.05);
}

.foo:hover {
  -webkit-transform: scale3d(1, 1, 1);
  -moz-transform: scale3d(1, 1, 1);
  -ms-transform: scale3d(1, 1, 1);
  transform: scale3d(1, 1, 1);
}
<div class="foo"></div>

我不希望边缘呈锯齿状。我曾尝试在这里使用-webkit-backface-visibility: hidden,但没有运气。我知道有一个名为-webkit-font-smoothing 的属性,我们可以将字体平滑设置为antialiased。有什么方法可以将antialiased 设置为div?

截图 2

最后,这不是我的问题的解决方案,我想避免使用这种解决方法,因为我必须手动计算 scale3d() 的参数值。

我在这里期待第一种情况的解决方案。

【问题讨论】:

  • 在 Retina Macbook Pro 上 OSX 上的 Chrome 39 上,它不是像素级的,但阴影是一系列矩形。您也许可以将圆圈的大小放大一点,例如宽度:100 像素,高度:100 像素,然后从 0.2 的初始比例开始,然后将其放大到 5(或任何值),这对我来说似乎更好。那么这只会扩大一点,这似乎可以解决错误。
  • 感谢您的信息。我在 Windows 上使用 Chrome 37 64 位。这是您建议的更新小提琴:jsfiddle.net/aniskhan001/bk96d9vo/1 .. 我仍然看到它是像素化的,但比以前少了一点。这只是一个例子。在我的项目中,我将不得不将 div 变得更大。
  • imgur.com/hb8RAHY 对我来说是这样的 - 根本没有像素化,但嵌入的阴影确实不好。代替嵌入阴影,也许您可​​以尝试径向渐变?
  • 刚刚用 Chrome 39 试了一下,对我来说,它看起来比你现在发布的要好。 imgur.com/f6vy3j6 我认为这取决于 GPU 渲染。我使用的是 NVIDIA GTX 560。但是,Chrome 37、Opera 23 等其他浏览器呢?
  • 我认为这是一个 @2x 屏幕而不是 GPU 问题的错误 - 不过可能是错误的。你试过径向渐变吗?您可能会发现巧合地解决了这个问题。我会在这里为 chrome 提交两个问题 - 一个针对您拥有的像素版本,另一个针对缩放插入框阴影的问题。

标签: css google-chrome webkit css-transitions


【解决方案1】:

我认为解决此问题的唯一方法是先按比例缩小元素,然后按 Mazhar Ahmed 已经回答的方式将其缩放到正常大小。

如果你不想手动计算大小,你可以像这样使用 CSS 变量:

--scale:0.1;

.element{
  width: 40px * (1 / var(--scale));
  height: 40px * (1 / var(--scale));
  transform: scale(var(--scale));
}

.element:hover{
  transform:scale(1);
}

如您所见,您只需在变量中定义比例因子。 CSS 完成其余的工作并相应地设置宽度和高度。
所以在我们的例子中,元素是 400x400px,但它被缩小了,所以它看起来是我们 CSS 中定义的 40x40px。

对于懒骨头(比如我)来说只是一个小小的补充。

【讨论】:

    【解决方案2】:

    这会做更多的工作,但您可能需要考虑不使用比例。

    如果您打算调整 css 形状的大小,您可能只需转换用于绘制形状的属性并使用包装 div 进行定位即可。

    Working Example

    html:

    <div class="row"> <!-- use a parent div to create rows -->
        <div class="wrap"> <!-- use a wrapper to position -->
            <div class="foo"></div>
        </div>
        <div class="wrap">
            <div class="foo"></div>
        </div>
        <div class="wrap">
            <div class="foo"></div>
        </div>
        <div class="wrap">
            <div class="foo"></div>
        </div>
        <div class="wrap">
            <div class="foo"></div>
        </div>
        <div class="wrap">
            <div class="foo"></div>
        </div>
    </div>
    <div class="row">
        <div class="wrap">
            <div class="foo"></div>
        </div>
        <div class="wrap">
            <div class="foo"></div>
        </div>
        <div class="wrap">
            <div class="foo"></div>
        </div>
    </div>
    

    css:

    .wrap {
        position: relative;
        height:20px;
        width:20px;
        display: inline-block;
    }
    .foo {
        position: absolute;
        top: 190px;
        left: 190px;
        background: #4FC093;
        display: block;
        width: 20px;
        height: 20px;
        box-shadow: 0 0 10px inset;
        border-radius: 50%;
        cursor: pointer;
        transition:all 3s ease;
        z-index: 99;/*using an unnecessarily large z-index makes for a nicer transition in Chrome*/
    }
    .foo:hover {
        top: 0px;
        left: 0px;
        width: 400px;
        height: 400px;
        box-shadow: 0 0 200px inset;
        transition:all 3s ease;
        z-index: 1;
    }
    

    【讨论】:

    • 感谢您的回答。但我想像这个演示一样对齐多个.foos:jsfiddle.net/bk96d9vo/2 同时在width 和height 上转换给我一个滞后的效果,不知道为什么。
    • @aniskhan001 查看更新。如果这不是你想要的,试试这个:jsfiddle.net/aa6zjg5p/6
    • 感谢您抽出宝贵时间。我更喜欢在absolute div 上使用比例的原因不是为了改变主体/父元素的实际宽度和高度。这显示在您的示例中。我在想,这是 webkit 浏览器的 bug 尚未修复。
    【解决方案3】:

    是的,有一个修复方法,在初始状态下使元素变大并缩小。然后悬停比例为 1,现在它非常平滑且没有像素化。

    .foo {
        background: #4FC093;
        display: block;
        position: absolute;
        width: 200px;
        height: 200px;
        box-shadow: 0 0 10px inset;
        margin: 0 auto;
        border-radius: 50%;
        left: 50%;
        top: 50%;
        cursor: pointer;
        -webkit-transition: all 3s ease;
        -moz-transition: all 3s ease;
        -ms-transition: all 3s ease;
        transition: all 3s ease;
    
        -webkit-transform: scale(.20);
        -moz-transform: scale(.20);
        -ms-transform: scale(.20);
        transform: scale(.20);
    }
    
    .foo:hover {
        -webkit-transform: scale(1);
        -moz-transform: scale(1);
        -ms-transform: scale(1);
        transform: scale(1);
    }
    

    【讨论】:

    • 感谢您的回答。我在我的问题中提到我想避免使用这种方法。因为我必须通过手动计算来更改 scale() 的值。但如果问题得到解决,那很好。这是我更新的小提琴,它与我最终想要做的非常相似:jsfiddle.net/bk96d9vo/2 现在唯一的问题是如果我增加这些 div 的大小,我将面临一些定位问题。它们不会像我预期的那样对齐。
    • 你为什么不计算比例并总是让它小于1?一点都不难。
    • @aniskhan001 绝对定位元素。那么它们实际上有多大并不重要
    • 好的,这是更新:jsfiddle.net/bk96d9vo/3 你可以看到定位问题。 @ZachSaucier,将这些元素位置设置为绝对位置,使它们完全聚集在一个地方。
    • @aniskhan001 这就是为什么你要用right 和left 来定位它们,就像你总是用绝对定位的元素一样
    猜你喜欢
    • 1970-01-01
    • 2010-10-30
    • 2017-06-21
    • 2014-12-18
    • 2013-06-16
    • 2014-04-05
    • 1970-01-01
    • 2017-08-07
    • 2011-01-17
    相关资源
    最近更新 更多