diff options
Diffstat (limited to 'files/zh-cn/web/events/mozafterpaint/index.html')
-rw-r--r-- | files/zh-cn/web/events/mozafterpaint/index.html | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/files/zh-cn/web/events/mozafterpaint/index.html b/files/zh-cn/web/events/mozafterpaint/index.html new file mode 100644 index 0000000000..fc3b766b45 --- /dev/null +++ b/files/zh-cn/web/events/mozafterpaint/index.html @@ -0,0 +1,179 @@ +--- +title: MozAfterPaint +slug: Web/Events/MozAfterPaint +translation_of: Archive/Add-ons/Events/MozAfterPaint +--- +<p><code>MozAfterPaint事件在页面呈现给用户屏幕时触发,并提供页面重绘的信息,主要应用于页面优化审查。</code></p> + +<p><code>注意</code>MozAfterPaint并非在页面重绘时立即触发,而是在重绘并合成后发生。这意味着有部分内容触发时已经呈现给客户。</p> + +<div class="note"><strong>Note:</strong> + +<ul> + <li>This event is available to add-ons but since Firefox 4 it is <strong>not</strong> available to web pages by default. It can only be made available to web pages by setting the preference <code>dom.send_after_paint_to_content</code> to <code>true</code>. (源于<strong> </strong><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=539356"><strong>Bug 539356</strong></a>, 这个属性设置为<code>true</code>, 所有的<code>MozAfterPaint</code> 时间都被发动到web页面. 更多信息请查看 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=829330"><strong>Bug 829330</strong></a>)</li> + <li>Web pages that want to take an action after a repaint of the page can use <a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a> with a callback that sets a timeout of zero to then call the code that takes the desired post-repaint action.</li> + <li>If the handler for this event does anything that triggers repainting (such as changing the style of an element), an infinite loop will probably be triggered.</li> + <li>Repainting of areas scrolled outside the viewport is reported, but repainting of areas scrolled outside <code>overflow:auto</code> elements and the like is not.</li> + <li>Repainting in windowed plug-ins (which is most plug-ins on Windows and GTK) is not reported.</li> +</ul> +</div> + +<h2 id="General_info">General info</h2> + +<dl> + <dt style="float: left; text-align: right; width: 120px;">Specification</dt> + <dd style="margin: 0 0 0 120px;"><em>Add-ons specific</em></dd> + <dt style="float: left; text-align: right; width: 120px;">Interface</dt> + <dd style="margin: 0 0 0 120px;">Event</dd> + <dt style="float: left; text-align: right; width: 120px;">Bubbles</dt> + <dd style="margin: 0 0 0 120px;">Yes</dd> + <dt style="float: left; text-align: right; width: 120px;">Cancelable</dt> + <dd style="margin: 0 0 0 120px;">Yes</dd> + <dt style="float: left; text-align: right; width: 120px;">Target</dt> + <dd style="margin: 0 0 0 120px;">window</dd> + <dt style="float: left; text-align: right; width: 120px;">Default Action</dt> + <dd style="margin: 0 0 0 120px;">None</dd> +</dl> + +<h2 id="Properties">Properties</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col">Type</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyInline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>The event target (the topmost target in the DOM tree).</td> + </tr> + <tr> + <td><code>type</code> {{readonlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The type of event.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyInline}}</td> + <td><code>boolean</code></td> + <td>Does the event normally bubble?</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyInline}}</td> + <td><code>boolean</code></td> + <td>Is it possible to cancel the event?</td> + </tr> + <tr> + <td><code>boundingClientRect</code></td> + <td>clientRect</td> + <td>The equivalent of {{domxref("Element.getBoundingClientRect", "getBoundingClientRect()")}} for the repainted zone. Read only.</td> + </tr> + <tr> + <td><code>clientRects</code></td> + <td>clientRectList</td> + <td>The equivalent of {{domxref("Element.getClientRects", "getClientRects()")}} for the repainted zone. Read only.</td> + </tr> + <tr> + <td><code>transactionId</code></td> + <td><code>uint64_t</code></td> + <td>The transaction id of the composition that just occurred to present something to the user. Read only.</td> + </tr> + </tbody> +</table> + +<h2 id="Example">Example</h2> + +<p>This example highlights elements that get repainted while hovering the document with a cursor.</p> + +<pre class="brush: js">(function(){ + var store = []; + + // every repaint will be logged in store + window.addEventListener("MozAfterPaint", log, false); + + if ( document.body ) + bind(); + else + window.addEventListener("load", bind, false); + + function log(e){ + store.push( [(new Date).getTime(), e.clientRects] ); + } + + function bind(){ + // clicking anywhere on the document will prevent other repaint to be logged + // as well as display the visual "repaint heatmap" + document.body.addEventListener("click", function onClick(){ + window.removeEventListener("MozAfterPaint", log, false); + + for ( var pos = 0; pos < store.length; pos++ ) { + var rects = store[pos][1]; + + for ( var i = 0; i < rects.length; i++ ) { + // will simply "draw" semi-transparent red divs where + // repaints where recorded + var rect = rects[i]; + var div = document.createElement("div"); + + with (div.style) { + background = "red"; + opacity = "0.1"; + position = "absolute"; + top = rect.top + "px"; + left = rect.left + "px"; + width = (rect.right - rect.left) + "px"; + height = (rect.bottom - rect.top) + "px"; + } + + document.body.appendChild( div ); + } + } + + document.body.removeEventListener("click", onClick, false); + }, false); + } +})(); +</pre> + +<p>This example is for measuring how long something took to paint to the user.</p> + +<pre class="brush: js">// Suppose we want to measure how long it takes to paint the +// next frame after a click event is fired on element "target". + +let winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + +// The last transaction id is the last id that was sent to the +// compositor before our script started to execute. +let lastTransactionId = winUtils.lastTransactionId; +let start = window.performance.now(); + +// Set up our MozAfterPaint listener, but we only care about +// MozAfterPaint events where the transaction id is GREATER +// than lastTransactionId. This is to account for the possibility +// that a composite is underway at the time this script is running. +addEventListener("MozAfterPaint", function onPaint(event) { + if (event.transactionId > lastTransactionId) { + // Since the transaction id is greater than the last transaction + // id, that means we're safe to assume that whatever effect that + // clicking on the "target" element was supposed to have, if the + // change should have been instantaneous, then it has been presented + // to the user. + let finish = window.performance.now(); + alert(`Time to present: ${finish - start}ms`); + removeEventListener("MozAfterPaint", onPaint); + } +}); + +document.getElementById("target").click(); + +</pre> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIDOMWindowUtils#isMozAfterPaintPendingen-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIDOMWindowUtils#isMozAfterPaintPending">nsIDOMWindowUtils.isMozAfterPaintPending</a></li> +</ul> |