如何在 Safari 中的 WebKit 3D 转换后强制重新渲染

Posted

技术标签:

【中文标题】如何在 Safari 中的 WebKit 3D 转换后强制重新渲染【英文标题】:How to force re-render after a WebKit 3D transform in Safari 【发布时间】:2011-06-06 04:56:10 【问题描述】:

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

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

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

只有在使用 3D 变换时才会出现这种效果。使用时一切正常

-webkit-transform: scale(2);

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

有人知道如何告诉 Safari 以新的比例重新渲染 div 吗?

【问题讨论】:

你怎么知道浏览器没有重新渲染 DIV 的内容?是否包含图片com 【参考方案1】:

文字模糊的原因是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

【讨论】:

为我工作,虽然在那些 2x'ed 缩放元素的边距和填充周围有一些非常奇怪的行为。【参考方案2】:

我发现在出于其他原因(重新计算悬停时的文本溢出)尝试在 safari 中强制重绘 div 时,这很简单:

selector 
    /* your rules here */

selector:hover 
    /* your rules here */

selector:hover:after 
    content:"";

我在悬停时做了一些改变填充以适应某些按钮的操作,但在 safari/chrome 中它不能正确重新计算内容,添加 :after 伪类就可以了。

【讨论】:

【参考方案3】:

我正在尝试做同样的事情。我认为这里发生的事情是 Safari 只是在缩放像素。也就是说,它会完成所有“正常”的浏览器渲染,然后缩放结果的像素。

示例:将相对高质量的图像(例如 1000x1000 像素)放置在一个小 div(200x200 像素)中,并将图像设置为 100% 的宽度和高度。当您将 div 3D 转换为 5 倍时,结果在 Safari 中会模糊,在 Chrome 中会清晰。使用 2D 变换,图像在两者中都会显得清晰。

解决方法是在完成 3D 后转换为 2D 变换。但是,我发现在转换之间进行转换时会有一点延迟,所以这对我来说效果不太好。

【讨论】:

【参考方案4】:

我找不到在 Safari(桌面版 v7.0.2 和 iOS 6.1.3 和 7.0.6 中包含的版本)中使放大不模糊的修复程序,但我在某个时候做到了,请注意我得到了当我将比例设置为 5 时,我的 png 清晰。我不知道为什么,因为我的代码版本在我所做的所有后续更改中都丢失了。所有其他比例因子都很模糊。

由于 iPhone 和 iPad 是该项目的目标设备,因此我最终放弃了缩放变换和动画图像高度。我很失望 Safari 团队决定以一种在很多情况下使它们成为不可行的选择的方式来实现转换。

【讨论】:

【参考方案5】:

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

到目前为止,我发现的唯一解决方案是隐藏图像(或包含图像的 div),然后再次显示。可以使用 opacity=0 或 visibility=hidden,但实际上必须至少在一两帧内不可见。

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

【讨论】:

【参考方案6】:

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

一种解决方案是隐藏(不透明度,可见性)图像几帧(或包装图像/图像/无论它是什么的容器)......我在另一篇关于 SO 的帖子中找到的更好的解决方案是这个(在包含 DIV 上发布):

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

顺便说一句,我的东西只是普通的 2d 东西,但 translateZ 似乎有所作为,尽管我从未接触过任何 3d 东西。

【讨论】:

以上是关于如何在 Safari 中的 WebKit 3D 转换后强制重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

Webkit中的细化文本(Safari)

如何在 chrome、safari、opera 等 webkit 浏览器中删除 c fakepath?

如何强制iPad / iPhone Safari使用旧版本的Webkit?

css3怎么让3d旋转的层近大远小

iOS8 Safari -webkit-overflow-scrolling:触摸;问题

盒模型display:-webkit-box;(转)