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>
0 commit comments