如何在Safari中进行WebKit 3D变换后强制重新渲染?

26

我正在使用CSS 3D变换来缩放一个div,例如:

-webkit-transform: scale3d(2,2,1);

在任何 WebKit 浏览器中,缩放本身都可以正常工作。然而,在 Safari(移动版或 Windows 版)上使用时,div 元素的内容不会重新渲染。其结果是,缩放后的内容变得模糊。

只有在使用 3D 变换时才会出现这种效果。当使用 -webkit-transform: scale(2); 时一切正常。

为了在 iPhone/iPad 上利用硬件加速,最好使用 3D 变换。

有人知道如何告诉 Safari 使用新的缩放比例重新渲染 div 吗?


你怎么知道浏览器没有重新渲染 DIV 的内容?它是否包含图像? - JoshNaro
6个回答

31

文本模糊的原因是由于Webkit将文本视为图像,我猜这就是硬件加速的代价。我假设您正在使用UI中的转换或动画关键帧,否则性能提升微不足道,您应该切换到非3D变换。

您可以选择:

• 添加一个transitionend事件监听器,然后将3D变换替换为标准变换,例如...

element.addEventListener("transitionend", function() {
  element.style.webkitTransform = 'scale(2,2)'
},false);

• 由于Webkit将内容视为图像,最好从大的状态开始并缩小它。因此,应该在“结束状态”编写css,并将其缩小为普通状态...

 #div {
  width: 200px; /*double of what you really need*/
  height: 200px; /*double of what you really need*/
  webkit-transform: scale3d(0.5, 0.5, 1);
}

 #div:hover {
  webkit-transform: scale3d(1, 1, 1);
}

当你悬停在上面时,会得到一个脆脆的文本效果。 我在这里制作了一个演示(在iOS上也可以使用):

http://duopixel.com/stack/scale.html


2
对我来说可行,尽管在这些2倍缩放的元素周围的边距和填充方面存在一些非常奇怪的行为。 - matt

6

我发现在尝试强制重绘Safari中的一个div(为了其他原因,例如悬停时重新计算文本溢出)时,方法很简单:

selector {
    /* your rules here */
}
selector:hover {
    /* your rules here */
}
selector:hover:after {
    content:"";
}

我在hover时做了一些改变padding的操作来适应一些按钮,但在Safari/Chrome中它没有正确地重新计算内容,添加:after伪类解决了这个问题。


2
我也想做同样的事情。我认为这里发生的事情是Safari只是缩放像素。也就是说,它进行了所有“正常”的浏览器渲染,然后缩放结果的像素。
例如:将一个相对高质量的图像(比如1000x1000像素)放在一个小的div(200x200像素)中,并将图像设置为100%的宽度和高度。当你将div进行3D变换以放大5倍时,在Safari中结果会模糊,在Chrome中则清晰。使用2D变换,图像在两个浏览器中都会显示得很清晰。
一种解决方法是在完成3D后转换为2D变换。但是,我发现在变换之间转换会有轻微的延迟,所以这对我来说效果不太好。

0

我找不到解决方案,使得在Safari(桌面版v7.0.2和iOS 6.1.3和7.0.6中包含的版本)中缩放不会模糊,但是我曾经注意到,当我将比例设置为5时,我得到了一个清晰的png。我不知道为什么,因为我的代码版本在随后所做的所有更改中都丢失了。所有其他比例因子都很模糊。

由于iPhone和iPad是该项目的目标设备,因此最终我放弃了比例变换,而是通过动画图像高度来实现。我对Safari团队决定以许多情况下使它们成为不可行选项的方式实现变换感到失望。


0

嗯...我在使用Chrome 53尝试放大Google地图图像(hidpi)时遇到了同样的问题。

到目前为止,我找到的唯一解决方案是隐藏图像(或包含图像的div),然后再次显示它。 可以使用opacity = 0或visibility = hidden,但实际上至少要在一个帧中将其设置为不可见。

顺便说一句,这甚至不是3D变换。只是2D东西。


0

嗯...我在使用Chrome 53时,尝试放大Google地图图像(hidpi)时遇到了相同的问题。

一个解决方案是在几帧(或包装图像/图像/任何东西的容器)中隐藏(不透明度,可见性)图像...更好的解决方案是我在SO上的另一篇文章中发现的(在包含DIV上发布):

e.style.transform = 'translateZ(0) scale(1.0, 1.0)'

顺便说一下,我的东西只是普通的2D内容,不过translateZ似乎有所不同,尽管我从未涉及任何3D方面的东西。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接