3d-point-mapping-2-transforminterop.html (6329B)
1 <!DOCTYPE html> 2 <title>More point mapping through 3D transform hierarchies</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 #box1, #box5, #box9 { 22 height: 140px; 23 width: 140px; 24 margin: 20px; 25 background-color: #DDD; 26 border: 1px solid black; 27 box-sizing: border-box; 28 perspective: 400px; 29 } 30 31 #box2, #box6, #box10 { 32 position: relative; 33 height: 100px; 34 width: 100px; 35 padding: 20px; 36 margin: 20px; 37 border: 1px solid black; 38 background-color: #81AA8A; 39 transform-style: preserve-3d; 40 transform: rotateY(-30deg); 41 box-sizing: border-box; 42 } 43 44 #box3 { 45 position: relative; 46 height: 100px; 47 width: 100px; 48 padding: 20px; 49 margin: 20px; 50 border: 1px solid black; 51 background-color: #81AA8A; 52 transform-style: preserve-3d; 53 box-sizing: border-box; 54 } 55 56 #box4, #box8, #box12 { 57 height: 90px; 58 width: 90px; 59 background-color: blue; 60 border: 1px solid black; 61 box-sizing: border-box; 62 transform: rotateY(30deg); 63 } 64 65 #box7 { 66 position: relative; 67 padding-left: 20px; 68 height: 100px; 69 width: 100px; 70 box-sizing: border-box; 71 background-color: #DDD; 72 border: 1px solid black; 73 } 74 75 #box11 { 76 padding-left: 20px; 77 height: 100px; 78 width: 100px; 79 box-sizing: border-box; 80 background-color: #DDD; 81 border: 1px solid black; 82 } 83 84 [id^="box"]:hover { 85 outline: 3px solid orange; 86 } 87 </style> 88 89 <body> 90 91 <div class="test"> 92 <!-- preserve-3d element with no transform--> 93 <div id="box1"> 94 <div id="box2"> 95 <div id="box3"> 96 <div id="box4"> 97 </div> 98 </div> 99 </div> 100 </div> 101 </div> 102 103 <div class="test"> 104 <!-- layer with no transform--> 105 <div id="box5"> 106 <div id="box6"> 107 <div id="box7"> 108 <div id="box8"> 109 </div> 110 </div> 111 </div> 112 </div> 113 </div> 114 115 <div class="test"> 116 <!-- non-layer with no transform--> 117 <div id="box9"> 118 <div id="box10"> 119 <div id="box11"> 120 <div id="box12"> 121 </div> 122 </div> 123 </div> 124 </div> 125 </div> 126 127 <script> 128 class Point { 129 constructor(x, y) { 130 this.x = x; 131 this.y = y; 132 } 133 }; 134 // Each test case defines four test points near the corners of an element area. 135 // - Point 1: Top-left 136 // - Point 2: Top-right 137 // - Point 3: Bottom-left 138 // - Point 4: Bottom-right 139 const tests = [{ 140 expectedElemId: 'box1', 141 points: [ 142 new Point(68, 66), // Hits box1 due to box2's transformation. 143 new Point(175, 45), 144 new Point(62, 155), // Hits box1 due to box2's transformation. 145 new Point(100, 175), 146 ] 147 }, 148 { 149 expectedElemId: 'box2', 150 points: [ 151 new Point(75, 70), 152 new Point(155, 63), 153 new Point(75, 155), 154 new Point(100, 156), // Hits box2 due to box3 preserving parent's transformed space. 155 ] 156 }, 157 { 158 expectedElemId: 'box3', 159 points: [ 160 new Point(108, 106), 161 new Point(198, 106), 162 new Point(108, 198), 163 // Bottom-right area is overlapped by box4. 164 ] 165 }, 166 { 167 expectedElemId: 'box4', 168 points: [ 169 new Point(120, 128), // Hits box3 if box4 were untransformed. 170 new Point(210, 128), 171 new Point(120, 198), // Hits box3 if box4 were untransformed. 172 new Point(210, 215), 173 ] 174 }, 175 { 176 expectedElemId: 'box5', 177 points: [ 178 new Point(312, 67), // Hits box5 due to box6's transformation. 179 new Point(423, 47), 180 new Point(312, 155), // Hits box5 due to box6's transformation. 181 new Point(331, 175), // Hits box5 due to box7 preserving parent's transformed space. 182 ] 183 }, 184 { 185 expectedElemId: 'box6', 186 points: [ 187 new Point(328, 86), // Hits box6 due to box7 preserving parent's transformed space. 188 new Point(400, 63), 189 new Point(328, 151), // Hits box6 due to box7 preserving parent's transformed space. 190 // The bottom-right area is overlapped by box7. 191 ] 192 }, 193 { 194 expectedElemId: 'box7', 195 points: [ 196 new Point(354, 87), // Hits box7 due to box8's transformation. 197 // The top-right area is overlapped by box8. 198 new Point(354, 171), // Hits box7 due to box8's transformation. 199 new Point(421, 185), 200 ] 201 }, 202 { 203 expectedElemId: 'box8', 204 points: [ 205 new Point(359, 87), 206 new Point(428, 84), 207 new Point(359, 168), 208 new Point(428, 175), 209 ] 210 }, 211 { 212 expectedElemId: 'box9', 213 points: [ 214 new Point(556, 65), // Hits box9 due to box10's transformation. 215 new Point(669, 46), 216 new Point(556, 157), // Hits box9 due to box10's transformation. 217 new Point(576, 174), // Hits box9 due to box11 preserving parent's transformed space. 218 ] 219 }, 220 { 221 expectedElemId: 'box10', 222 points: [ 223 new Point(568, 69), 224 new Point(646, 62), 225 new Point(568, 153), 226 new Point(576, 154), // Hits box10 due to box11 preserving parent's transformed space. 227 ] 228 }, 229 { 230 expectedElemId: 'box11', 231 points: [ 232 new Point(600, 87), // Hits box11 due to box12's transformation. 233 // The top-right area is overlapped by box12. 234 new Point(600, 170), 235 new Point(669, 185), 236 ] 237 }, 238 { 239 expectedElemId: 'box12', 240 points: [ 241 new Point(605, 87), 242 new Point(673, 85), 243 new Point(605, 170), 244 new Point(675, 175), 245 ] 246 } 247 ]; 248 249 tests.forEach(testcase => { 250 test(t => { 251 const expectedElem = document.getElementById(testcase.expectedElemId); 252 for (const point of testcase.points) { 253 const hitElem = document.elementFromPoint(point.x, point.y); 254 assert_equals(hitElem, expectedElem, 255 `point (${point.x}, ${point.y}) is inside element ${testcase.expectedElemId}`); 256 } 257 }, `${document.title}, hittesting ${testcase.expectedElemId})`); 258 }); 259 </script> 260 261 </html>