3d-point-mapping-origins.html (6777B)
1 <!DOCTYPE html> 2 <title>Point mapping through 3D transforms with origins</title> 3 <link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 7 <style type="text/css" media="screen"> 8 body { 9 margin: 0; 10 border: 1px solid black; 11 } 12 13 .test { 14 display: inline-block; 15 height: 200px; 16 width: 200px; 17 border: 1px solid black; 18 margin: 20px; 19 } 20 21 .perspective-container { 22 height: 140px; 23 width: 140px; 24 margin: 20px; 25 border: 1px solid black; 26 box-sizing: border-box; 27 perspective: 400px; 28 perspective-origin: 20% 80%; 29 } 30 31 .transformed-parent { 32 position: relative; 33 height: 100px; 34 width: 100px; 35 padding: 20px; 36 margin: 20px; 37 border: 1px solid black; 38 box-sizing: border-box; 39 transform: translateZ(100px) rotateY(-40deg); 40 transform-origin: 20% 40%; 41 } 42 43 .light-gray-box { 44 background-color: #DDD; 45 } 46 47 .medium-gray-box { 48 background-color: #AAA; 49 } 50 51 .blue-box { 52 height: 100px; 53 width: 100px; 54 box-sizing: border-box; 55 background-color: blue; 56 border: 1px solid black; 57 } 58 59 .green-box { 60 height: 100px; 61 width: 100px; 62 padding: 20px; 63 box-sizing: border-box; 64 background-color: #C0D69E; 65 border: 1px solid black; 66 } 67 68 .layered { 69 position: relative; 70 } 71 72 div[id]:hover { 73 outline: 3px solid orange; 74 } 75 </style> 76 77 <body> 78 <div class="test"> 79 <!-- Simple transformed div in perspective --> 80 <div class="perspective-container light-gray-box" id="top-left-light-gray"> 81 <div class="transformed-parent medium-gray-box" id="top-left-medium-gray"> 82 </div> 83 </div> 84 </div> 85 86 <div class="test"> 87 <!-- Transformed div in perspective with non-layer child --> 88 <div class="perspective-container light-gray-box" id="top-right-light-gray"> 89 <div class="transformed-parent medium-gray-box" id="top-right-medium-gray"> 90 <div class="blue-box" id="top-right-blue"> 91 </div> 92 </div> 93 </div> 94 </div> 95 <br> 96 97 <div class="test"> 98 <!-- Transformed div in perspective with layer child --> 99 <div class="perspective-container light-gray-box" id="bottom-left-light-gray"> 100 <div class="transformed-parent medium-gray-box" id="bottom-left-medium-gray"> 101 <div class="blue-box layered" id="bottom-left-blue"> 102 </div> 103 </div> 104 </div> 105 </div> 106 107 <div class="test"> 108 <!-- Transformed div in perspective with child having layer child --> 109 <div class="perspective-container light-gray-box" id="bottom-right-light-gray"> 110 <div class="transformed-parent medium-gray-box" id="bottom-right-medium-gray"> 111 <div class="green-box" id="bottom-right-green"> 112 <div class="blue-box layered" id="bottom-right-blue"> 113 </div> 114 </div> 115 </div> 116 </div> 117 </div> 118 </body> 119 120 <script> 121 class Point { 122 constructor(x, y) { 123 this.x = x; 124 this.y = y; 125 } 126 }; 127 // Each test case defines four test points near the corners of an element. 128 // - Point 1: Top-left 129 // - Point 2: Top-right 130 // - Point 3: Bottom-left 131 // - Point 4: Bottom-right 132 const tests = [{ 133 expectedElemId: 'top-left-light-gray', 134 points: [ 135 new Point(48, 48), 136 new Point(60, 48), 137 new Point(48, 172), 138 new Point(175, 172), 139 ] 140 }, 141 { 142 expectedElemId: 'top-left-medium-gray', 143 points: [ 144 new Point(70, 41), // Inside top-left-light-gray without transform-origin. 145 new Point(182, 12), // Inside main document without transform-origin. 146 new Point(70, 158), 147 new Point(182, 158), 148 ] 149 }, 150 { 151 expectedElemId: 'top-right-light-gray', 152 points: [ 153 new Point(290, 45), 154 new Point(308, 45), 155 new Point(290, 175), 156 new Point(327, 175), 157 ] 158 }, 159 { 160 expectedElemId: 'top-right-medium-gray', 161 points: [ 162 new Point(315, 40), // Inside top-right-light-gray without transform-origin. 163 new Point(427, 12), 164 new Point(315, 158), 165 // The bottom-right area is overlapped by top-right-blue. 166 ] 167 }, 168 { 169 expectedElemId: 'top-right-blue', 170 points: [ 171 new Point(338, 64), 172 new Point(462, 36), 173 new Point(338, 186), 174 new Point(462, 197), 175 ] 176 }, 177 { 178 expectedElemId: 'bottom-left-light-gray', 179 points: [ 180 new Point(45, 290), 181 new Point(62, 290), 182 new Point(45, 420), 183 new Point(80, 420), 184 ] 185 }, 186 { 187 expectedElemId: 'bottom-left-medium-gray', 188 points: [ 189 new Point(70, 288), // Inside bottom-left-light-gray without transform-origin. 190 new Point(183, 256), 191 new Point(70, 404), // Inside bottom-left-light-gray without transform-origin. 192 // The bottom-right area is overlapped by bottom-left-blue. 193 ] 194 }, 195 { 196 expectedElemId: 'bottom-left-blue', 197 points: [ 198 new Point(92, 310), 199 new Point(216, 283), 200 new Point(90, 433), 201 new Point(216, 442), 202 ] 203 }, 204 { 205 expectedElemId: 'bottom-right-light-gray', 206 points: [ 207 new Point(290, 290), 208 new Point(307, 290), 209 new Point(290, 420), 210 new Point(325, 420), 211 ] 212 }, 213 { 214 expectedElemId: 'bottom-right-medium-gray', 215 points: [ 216 new Point(314, 288), // Inside bottom-right-light-gray without transform-origin. 217 new Point(430, 255), 218 new Point(314, 405), // Inside bottom-right-light-gray without transform-origin. 219 // The bottom-right area is overlapped by bottom-right-green. 220 ] 221 }, 222 { 223 expectedElemId: 'bottom-right-green', 224 points: [ 225 new Point(337, 309), // Inside bottom-right-medium-gray without transform-origin. 226 new Point(464, 284), // Inside main document without transform-origin. 227 new Point(337, 434), // Inside main document without transform-origin. 228 // The bottom-right area is overlapped by bottom-right-blue. 229 ] 230 }, 231 { 232 expectedElemId: 'bottom-right-blue', 233 points: [ 234 new Point(360, 334), // Inside bottom-right-green without transform-origin. 235 new Point(500, 316), // Inside main document without transform-origin. 236 new Point(360, 462), // Inside main document without transform-origin. 237 new Point(498, 480), // Inside main document without transform-origin. 238 ] 239 } 240 ]; 241 242 tests.forEach(testcase => { 243 test(t => { 244 const expectedElem = document.getElementById(testcase.expectedElemId); 245 for (const point of testcase.points) { 246 const hitElem = document.elementFromPoint(point.x, point.y); 247 assert_equals(hitElem, expectedElem, 248 `point (${point.x}, ${point.y}) is inside element ${testcase.expectedElemId}`); 249 } 250 }, `${document.title}, hittesting ${testcase.expectedElemId})`); 251 }); 252 </script> 253 254 </html>