7

我编写了一个小示例页面,其中包含可在触摸设备上拖动的元素(基于Peter-Paul Koch 的代码)。

我有两个可拖动<div>的元素:一个绿色块和一个红色球(用 做成球形border-radius)。拖动是用ontouchstart,ontouchmove和来实现的, ontouchend“动画”是通过改变这些元素的top和CSS 属性来完成的。left

当我拖着绿色的时候,全是玫瑰和马驹。

但是,当我在 iPad 1(运行 iOS 5.1.1)或 iPad 3(6.0.1)上的 Safari 中拖动红色的时候,我会在圆圈的后边缘处看到一些浅红色的痕迹(见下面的截图)。

但是,我没有在我的 iPhone 5 (6.1.4) 上看到这些痕迹。

我的元素上使用边框半径的工件

有没有办法摆脱这些痕迹?

(额外的问题:这种效果有术语吗?“重影”?“神器”?)

4

2 回答 2

20

修复

将此规则添加到您的#bawl { … }规则集中:

-webkit-transform: translateZ(0);

(如果您需要避免硬件加速,可以使用outline: 1px solid transparent— 更多详细信息,请参阅我对类似问题的回答。)

这会删除尾随的人工制品,但为什么呢?它结合了Quartz(iOS 中的绘图引擎)不将抗锯齿线条剪切到形状边缘以及 WebKit 如何在部分更改后重新绘制网页。

绘制网页

首先,快速和(过度)简化地介绍 WebKit 如何从 DOM 节点树到表示呈现网页的位图图像。

您已经知道网页被解析为元素树,称为 DOM。DOM 中的每个节点都以特定的方式呈现,具体取决于应用于它的样式。节点可能与其他节点重叠或被其他节点重叠,具体取决于 z 顺序、透明度、溢出、定位等。

这与引擎盖下的工作方式大体相似。WebKit 将每个 DOM 节点映射到一个对应的 DOM 节点RenderObject,该节点具有绘制单个 DOM 节点所需的所有信息。每个RenderObject都映射到它自己的或祖先的RenderLayer,这是处理节点如何“分层”的概念方式 - 即绘制在其他节点之上或之下。

为了呈现网页,每个网页都RenderLayer按 z 顺序从后向前绘制。该图层后面的孩子首先绘制,然后是图层本身,然后是它前面的孩子。为了绘制自身,RenderLayer调用它对应RenderObject的 s 上的 paint 方法。

WebKit 有两个用于渲染给定RenderLayer的代码路径:软件路径和硬件加速路径。软件路径将每个RenderObject直接绘制到您在浏览器中看到的渲染网页的图像上,而硬件路径允许RenderLayer将某些 s 指定为合成层,这意味着它和它的子级分别绘制并最终合成为一个GPU 生成的图像。RenderLayer只要页面上的一个或多个 s 需要硬件加速,或者浏览器中的标志(例如 Chrome)明确要求它,就会使用硬件路径。

更新网页的一部分

当动画或其他事件改变页面的一部分时,您不想重绘整个网页。相反,WebKit 在更改区域(损坏区域)周围绘制一个框,并且只重绘RenderLayer与该框重叠的每个部分。RenderLayer不与伤害矩形重叠的A将被完全跳过。

如果您通过软件路径进行渲染,WebKit 会直接将损坏的矩形重新组合到完整渲染页面的位图图像上,而图像的其余部分保持不变。但是,硬件路径会分别重新绘制每个合成层并将它们重新合成为新图像。

出了什么问题

translateZ修复将 3D 变换应用于元素。这迫使RenderLayer绘制球需要硬件加速,这意味着 WebKit 将使用硬件路径而不是软件路径。这意味着问题与使用软件路径有关。

当球被绘制时,边界半径意味着边缘是抗锯齿的。由于与 Quartz 相关的一个已知问题,形状的边缘是抗锯齿的,因此当您更改球在页面上的位置时,一些像素会落在计算的损坏矩形之外。使用软件路径,浏览器仅重绘渲染页面图像的更改区域,而图像的其余部分保持不变。落在此区域之外的半透明像素不会被更新,这是您移动球时留下的伪影的原因。

相比之下,硬件路径分别重绘该层(及其子层),然后重新组合页面。上次渲染该层时没有留下任何“幽灵像素”。

TL;博士

当 WebKit 使用软件渲染路径时,对部分页面的更改直接对代表整个页面的图像进行。出于性能原因,WebKit 仅重绘图像中已更改的那些部分。然而,当 Quartz 绘制一个圆角矩形时,它会对边缘进行抗锯齿处理,这样一些像素就会落在 WebKit 知道要重绘的区域之外。解决方法是通过应用 3D 变换强制该层需要硬件加速,这意味着该元素与页面的其余部分分开绘制并在之后重新组合。

于 2013-07-18T12:26:07.687 回答
0

在所有 webkit 浏览器(移动和桌面)上都有类似的问题。

我清除了缓存和所有内容,之后该错误从未发生。似乎我也只能看到它。我把它贴在这里并得到了很多反对意见,因为没有人也遇到过这个问题......

但是我尝试一下,可能会奏效

于 2013-07-16T13:06:05.700 回答