Files
sousa-gecko/testing/web-platform/tests/intersection-observer/v2/3d-transform-occlusion.html
T
Stefan Zager 5588549d33 Bug 2038864 [wpt PR 59807] - [IntersectionObserver] Fix occlusion detection with 3D transform, a=testonly
Automatic update from web-platform-tests
[IntersectionObserver] Fix occlusion detection with 3D transform

For regular (i.e. event-targeting) hit testing, z-axis ordering is
based on the z-axis position of the center of a PaintLayer. That's
not good enough for occlusion testing.

With this CL, when a hit test for occlusion encounters a 3d transform,
it computes the z-axis position of the four corners of the PaintLayer,
and if any of them are above any point in the occlusion target (i.e.
the HitTestRequest::stop_node_) then the PaintLayer is considered
occluding. This is not 100% accurate, but it will never result in a
false positive (i.e., reporting the target as unoccluded when it
actually is), which is a hard requirement of IntersectionObserver.

The corner-checking code makes a simplifying assumption that the
stop_node_ has no 3D projection, which is enforced by a call to
LayoutObject::HasDistortingVisualEffects from IntersectionObserver.

Bug: 479203484
Change-Id: Ida70f919efc73149d32112900b019987f27a5a7e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7835432
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Stefan Zager <szager@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1629048}

--

wpt-commits: 082be2f96b0c78e2784300a801fd88ff5b0f9425
wpt-pr: 59807
2026-05-13 04:24:06 +00:00

62 lines
1.5 KiB
HTML

<!DOCTYPE html>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
body {
transform-style: preserve-3d;
}
div {
position: absolute;
width: 100px;
height: 100px;
}
#target1, #target2 {
background: green;
}
#target2 {
left: 150px;
}
#occluder {
background: red;
transform: translateZ(-10px) rotateY(30deg);
transform-origin: center;
}
#behind {
left: 150px;
background: red;
transform: translateZ(-10px) rotateY(10deg);
transform-origin: center;
}
</style>
<div id=occluder></div>
<div id=target1></div>
<div id=behind></div>
<div id=target2></div>
<script>
promise_test(() => {
return Promise.all([
new Promise((resolve, reject) => {
const target = document.getElementById("target1");
new IntersectionObserver(entries => {
// part of #occluder is visible above #target1
assert_false(entries[0].isVisible);
resolve();
}, {trackVisibility:true, delay:100}).observe(target);
}),
new Promise((resolve, reject) => {
const target = document.getElementById("target2");
new IntersectionObserver(entries => {
// #behind is entirely behind #target2
assert_true(entries[0].isVisible);
resolve();
}, {trackVisibility:true, delay:100}).observe(target);
})
]);
}, "Intersection observer V2 test with occlusion by an element with a 3D transform.");
</script>