Mon, 25 Mar 2013 12:06:12 -0700
[css3-transforms] Fix syntax of transform-origin/perspective-origin properties.
1 <!DOCTYPE html public '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>
2 <html lang="en">
3 <head profile="http://www.w3.org/2006/03/hcard">
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
5 <title>CSS Transforms</title>
6 <link rel="stylesheet" type="text/css" href="../default.css" >
7 <script src='http://test.csswg.org/harness/annotate.js#CSS3-TRANSFORMS_DEV' type='text/javascript' defer></script>
9 <style type="text/css">
10 .term {
11 font-style: italic;
12 }
13 </style>
14 <link rel="stylesheet" type="text/css" href="http://www.w3.org/StyleSheets/TR/W3C-ED.css" >
16 </head>
17 <body>
18 <div id="div-head" class="head">
19 <!--logo-->
21 <h1>CSS Transforms</h1>
23 <h2 class="no-num no-toc">[LONGSTATUS] [DATE]</h2>
24 <dl>
25 <dt>This version:
26 <dd>
27 <a href="[VERSION]">http://dev.w3.org/csswg/css3-transforms/</a>
28 <!--http://www.w3.org/TR/[YEAR]/WD-[SHORTNAME]-[CDATE]/-->
29 <dt>Latest version:
30 <dd><a
31 href="http://www.w3.org/TR/css3-transforms/">[LATEST]</a>
32 <dt>Editor's draft:
33 <dd><a href="http://dev.w3.org/csswg/[SHORTNAME]/">http://dev.w3.org/csswg/[SHORTNAME]/</a>
34 <dt>Previous version:
35 <dd><a href='http://www.w3.org/TR/2012/WD-css3-transforms-20120911/'>http://www.w3.org/TR/2012/WD-css3-transforms-20120911/</a>
36 <dt id="editors-list">Editors:
37 <dd>Simon Fraser (<a href="http://www.apple.com/">Apple Inc</a>) <simon.fraser @apple.com>
38 <dd>Dean Jackson (<a href="http://www.apple.com/">Apple Inc</a>) <dino @apple.com>
39 <dd>Edward O'Connor (<a href="http://www.apple.com/">Apple Inc</a>) <eoconnor @apple.com>
40 <dd>Dirk Schulze (<a href="http://www.adobe.com/">Adobe Systems, Inc</a>) <dschulze @adobe.com>
41 <dd>Aryeh Gregor (<a href="http://www.mozilla.org/">Mozilla</a>) <ayg @aryeh.name>
43 <dt id="former-editors-list">Former Editors:
44 <dd>David Hyatt (<a href="http://www.apple.com/">Apple Inc</a>) <hyatt @apple.com>
45 <dd>Chris Marrin (<a href="http://www.apple.com/">Apple Inc</a>) <cmarrin @apple.com>
47 <dt>Issues list:
48 <dd><a href="https://www.w3.org/Bugs/Public/buglist.cgi?query_format=advanced&product=CSS&component=Transforms&resolution=---&cmdtype=doit">in Bugzilla</a>
50 <dt>Test suite:
51 <dd>none yet
52 </dl>
54 <!--copyright-->
56 <hr title="Separator for header">
57 </div>
59 <h2 class="no-num no-toc" id="abstract">Abstract</h2>
61 <p>CSS transforms allows elements styled with CSS to be transformed
62 in two-dimensional or three-dimensional space. This specification is the convergence of the
63 <a href="http://www.w3.org/TR/css3-2d-transforms/">CSS 2D transforms</a>,
64 <a href="http://www.w3.org/TR/css3-3d-transforms/">CSS 3D transforms</a>
65 and <a href="http://www.w3.org/TR/2009/WD-SVG-Transforms-20090320/">SVG transforms</a>
66 specifications.</p>
68 <h2 class="no-num no-toc" id="status">Status of this document</h2>
70 <!--status-->
72 <p>
73 This specification replaces the former <a href="http://www.w3.org/TR/css3-2d-transforms/" title="CSS 2D Transforms">CSS 2D Transforms</a> and <a href="http://www.w3.org/TR/css3-3d-transforms/" title="CSS 3D Transforms Module Level 3">CSS 3D Transforms</a> specifications, as well
74 as <a href="http://www.w3.org/TR/SVG-Transforms/" title="SVG Transforms 1.0">SVG Transforms</a>.
75 </p>
77 <p>
78 The <a href="ChangeLog">list of changes made to this specification</a> is
79 available.
80 </p>
82 <h2 class="no-num no-toc" id="contents">Table of contents</h2>
83 <!--toc-->
85 <h2>Introduction</h2>
87 <p><em>This section is not normative.</em></p>
88 <p>
89 The CSS <a href="http://www.w3.org/TR/REC-CSS2/visuren.html">visual
90 formatting model</a> describes a coordinate system within each
91 element is positioned. Positions and sizes in this coordinate space can
92 be thought of as being expressed in pixels, starting in the origin of point
93 with positive values proceeding to the right and down.
94 </p>
95 <p>
96 This coordinate space can be modified with the 'transform' property. Using transform,
97 elements can be translated, rotated and scaled in two or three dimensional space.
98 </p>
99 <p>
100 Additional properties make working with transforms easier, and allow the
101 author to control how nested three-dimensional transforms interact.
102 </p>
103 <ul>
104 <li>
105 The 'transform-origin' property provides a convenient way to control the origin about
106 which transforms on an element are applied.
107 </li>
108 <li>
109 The 'perspective' property allows the author to make child elements with
110 three-dimensional transforms appear as if they live in a common three-dimensional
111 space.
112 The 'perspective-origin' property provides control over the origin at which
113 perspective is applied, effectively changing the location of the "vanishing point".
114 </li>
115 <li>
116 The 'transform-style' property allows 3D-transformed elements and their 3D-transformed
117 descendants to share a common three-dimensional space, allowing the construction of
118 hierarchies of three-dimensional objects.
119 </li>
120 <li>
121 The 'backface-visibility' property comes into play when an element is flipped around
122 via three-dimensional transforms such that its reverse side is visible to the viewer.
123 In some situations it is desirable to hide the element in this situation, which is
124 possible using the value of ''hidden'' for this property.
125 </li>
126 </ul>
127 <p>
128 Note that while some values of the 'transform' property allow an element to be
129 transformed in a three-dimensional coordinate system, the elements themselves are not
130 three-dimensional objects. Instead, they exist on a two-dimensional plane (a flat
131 surface) and have no depth.
132 </p>
134 <!-- ======================================================================================================= -->
136 <h2 id="module-interactions">Module Interactions</h2>
137 <p>This module defines a set of CSS properties that affect the visual rendering of elements to which
138 those properties are applied; these effects are applied after elements have been sized and positioned according
139 to the <a href="http://www.w3.org/TR/CSS2/visuren.html" title="Visual formatting model">Visual formatting model</a>
140 from [[!CSS21]]. Some values of these properties result in the creation of a <a href="http://www.w3.org/TR/CSS2/visuren.html#containing-block" title="Visual formatting model">containing block</a>, and/or the creation of a <a href="http://www.w3.org/TR/CSS2/visuren.html#z-index" title="Visual formatting model">stacking context</a>.
141 </p>
142 <p>
143 Three-dimensional transforms can also affect the visual layering of elements, and thus override the back-to-front
144 painting order described in <a href="http://www.w3.org/TR/CSS2/zindex.html" title="Elaborate description of Stacking Contexts">Appendix E</a> of [[!CSS21]].
145 </p>
146 <p>
147 Transforms affect the rendering of backgounds on elements with a value of ''fixed'' for the
148 '<code class="property"><a href="http://www.w3.org/TR/css3-background/#the-background-attachment">background-attachment</a></code>' property,
149 which is specified in [[!CSS3BG]].
150 </p>
152 <h2 id="css-values">CSS Values</h2>
154 <p>This specification follows the <a href="http://www.w3.org/TR/CSS21/about.html#property-defs">CSS property definition conventions</a> from [[!CSS21]]. Value types not defined in this specification are defined in CSS LevelĀ 2 RevisionĀ 1 [[!CSS21]].</p>
156 <p>In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the <a href="http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit">inherit</a> keyword as their property value. For readability it has not been repeated explicitly.
159 <h2 id="definitions">Definitions</h2>
160 <p> When used in this specification, terms have the meanings assigned in
161 this section.
162 </p>
163 <dl>
164 <dt id="TermBoundingBox"><dfn>bounding box</dfn></dt>
165 <dd>
166 <p>
167 A bounding box is the object bounding box for all SVG elements
168 without an associated CSS layout box and the border box for all
169 other elements. The bounding box of a table is the border box
170 of its
171 <a href="http://www.w3.org/TR/CSS21/tables.html#model">table wrapper box</a>,
172 not its table box.
173 </p>
174 </dd>
176 <dt id="TermTransformableElement"><dfn>transformable element</dfn></dt>
177 <dd>
178 <p>
179 A transformable element is an element in one of these
180 categories:
181 </p>
182 <ul>
183 <li>
184 an element whose
185 layout is governed by the CSS box model which is either
186 a
187 <a href="http://www.w3.org/TR/CSS2/visuren.html#block-level">block-level</a>
188 or
189 <a href="http://www.w3.org/TR/CSS2/visuren.html#x13">atomic inline-level element</a>,
190 or whose 'display' property
191 computes to ''table-row'',
192 ''table-row-group'',
193 ''table-header-group'',
194 ''table-footer-group'',
195 ''table-cell'', or
196 ''table-caption'' [[!CSS21]]
197 </li>
198 <li>
199 an element in the SVG namespace and not governed by the CSS box model which has
200 the attributes 'transform', 'patternTransform' or 'gradientTransform' [[!SVG11]]
201 </li>
202 </ul>
203 </dd>
205 <dt id="TermLocalCoordinateSystem"><dfn>local coordinate system</dfn></dt>
206 <dd>
207 <p>
208 In general, a coordinate system defines locations and distances on the current
209 canvas. The current local coordinate system (also user coordinate system) is the
210 coordinate system that is currently active and which is used to define how
211 coordinates and lengths are located and computed, respectively, on the current
212 canvas.
213 </p>
214 </dd>
215 <dt id="TermUserCoordinateSystem"><dfn>user coordinate system</dfn></dt>
216 <dd>
217 <p>
218 See definition of <span class="term">local coordinate system</span>.
219 </p>
220 </dd>
221 <dt id="TermPerspectiveMatrix"><dfn>perspective matrix</dfn></dt>
222 <dd>
223 <p>
224 A matrix computed from the values of the 'perspective' and 'perspective-origin' properties as described <a href="#perspective-matrix-computation">below</a>.
225 </p>
226 </dd>
228 <dt id="TermTransformationMatrix"><dfn>transformation matrix</dfn></dt>
229 <dd>
230 <p>
231 A matrix that defines the mathematical mapping from one coordinate system into another. It is computed from the values of the 'transform' and 'transform-origin' properties as described <a href="#transformation-matrix-computation">below</a>.
232 </p>
233 </dd>
235 <dt id="TermCurrentTransformationMatrix"><dfn>current transformation matrix (CTM)</dfn></dt>
236 <dd>
237 <p>
238 A matrix that defines the mapping from the local coordinate system into the viewport coordinate system.
239 </p>
240 </dd>
242 <dt id="TermAccumulated3DTransformationMatrix">
243 <dfn>accumulated 3D transformation matrix</dfn>
244 </dt>
245 <dd>
246 <p>
247 A matrix computed for elements in a
248 <a href="#d-rendering-context">3D rendering context</a>, as
249 described
250 <a href="#accumulated-3d-transformation-matrix-computation">below</a>.
251 </p>
252 </dd>
254 <dt id="TermIdentityTransformFunction">
255 <dfn>identity transform function</dfn>
256 </dt>
257 <dd>
258 <p>
259 A <a href="#transform-functions">transform function</a> that is equivalent to a
260 identity 4x4 matrix (see <a href="#mathematical-description">Mathematical
261 Description of Transform Functions</a>). Examples for identity transform functions
262 are ''translate(0)'', ''translate3d(0, 0, 0)'', ''translateX(0)'',
263 ''translateY(0)'', ''translateZ(0)'', ''scale(1)'', ''scaleX(1)'', ''scaleY(1)'',
264 ''scaleZ(1)'', ''rotate(0)'', ''rotate3d(1, 1, 1, 0)'', ''rotateX(0)'',
265 ''rotateY(0)'', ''rotateZ(0)'', ''skew(0, 0)'', ''skewX(0)'', ''skewY(0)'', ''matrix(1, 0, 0, 1, 0,
266 0)'' and ''matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)''. A special
267 case is perspective: ''perspective(infinity)''. The value of m<sub>34</sub>
268 becomes infinitesimal small and the transform function is therefore assumed to be
269 equal to the identity matrix.
270 </p>
271 </dd>
273 <dt id="Term3DRenderingContext"><dfn>3D rendering context</dfn></dt>
274 <dd>
275 <p>
276 A containing block hierarchy of one or more levels, instantiated by elements with a
277 computed value for the 'transform-style' property of ''preserve-3d'', whose elements
278 share a common three-dimensional coordinate system.
279 </p>
280 </dd>
281 </dl>
283 <!-- ======================================================================================================= -->
285 <h2 id="two-dimensional-subset">
286 Two Dimensional Subset
287 </h2>
289 <p>
290 UAs may not always be able to render three-dimensional transforms and then just
291 support a two-dimensional subset of this specification. In this case <a
292 href="#three-d-transform-functions">three-dimensional transforms</a> and the
293 properties 'transform-style', 'perspective', 'perspective-origin' and
294 'backface-visibility' must not be supported. Section <a
295 href="#transform-3d-rendering">3D Transform Rendering</a> does not apply.
296 Matrix decomposing uses the technique taken from the "unmatrix" method in "Graphics
297 Gems II, edited by Jim Arvo", simplified for the 2D case. Section
298 <a href="#mathematical-description">Mathematical Description of Transform Functions</a>
299 is still effective but can be reduced by using a 3x3 transformation matrix where
300 <em>a</em> equals <em>m<sub>11</sub></em>, <em>b</em> equals <em>m<sub>12</sub></em>,
301 <em>c</em> equals <em>m<sub>21</sub></em>, <em>d</em> equals <em>m<sub>22</sub></em>,
302 <em>e</em> equals <em>m<sub>41</sub></em> and <em>f</em> equals <em>m<sub>42</sub></em>
303 (see <a href="#MatrixDefined">A 2D 3x2 matrix with six parameter</a>).
304 </p>
306 <div class="figure">
307 <img src="3x3matrix.png" alt="3x3 matrix" title="\begin{bmatrix} a & c & e \\ b
308 & d & f \\ 0 & 0 & 1 \end{bmatrix}" width="82" height="79">
309 <p class="caption">
310 3x3 matrix for two-dimensional transformations.
311 </p>
312 </div>
314 <div class="example">
315 <p>
316 Authors can easily provide a fallback if UAs do not provide support for
317 three-dimensional transforms. The following example has two property definitions
318 for 'transform'. The first one consists of two two-dimensional transform
319 functions. The second one has a two-dimensional and a three-dimensional transform
320 function.
321 </p>
322 <pre>div {
323 transform: scale(2) rotate(45deg);
324 transform: scale(2) rotate3d(0, 0, 1, 45deg);
325 }</pre>
327 <p>
328 With 3D support, the second definition will override the first one. Without 3D
329 support, the second definition is invalid and a UA falls back to the first
330 definition.
331 </p>
332 </div>
334 <!-- ======================================================================================================= -->
336 <h2 id="transform-rendering">The Transform Rendering Model</h2>
337 <p><em>This section is normative.</em></p>
338 <p>
339 Specifying a value other than ''none'' for the ''transform'' property establishes a
340 new <span class="term">local coordinate system</span> at the element that it is
341 applied to. The mapping from where the element would have rendered into that local
342 coordinate system is given by the element's <span class="term">transformation
343 matrix</span>. Transformations are cumulative. That is, elements establish their local
344 coordinate system within the coordinate system of their parent. From the perspective
345 of the user, an element effectively accumulates all the 'transform' properties of its
346 ancestors as well as any local transform applied to it. The accumulation of these
347 transforms defines a <span class="term">current transformation matrix (CTM)</span> for
348 the element.
349 </p>
350 <p>
351 The coordinate space is a
352 coordinate system with two axes: the X axis increases horizontally to the right; the
353 Y axis increases vertically downwards. Three-dimensional transform functions extend
354 this coordinate space into three dimensions, adding a Z axis perpendicular to the
355 plane of the screen, that increases towards the viewer.
356 </p>
358 <div class="figure">
359 <img src="coordinates.svg" width="270" height="240" alt="Demonstration of the initial coordinate space">
360 <p class="caption">
361 Demonstration of the initial coordinate space.
362 </p>
363 </div>
365 <p id="transformation-matrix-computation">
366 The <span class="term">transformation matrix</span> is computed
367 from the 'transform' and 'transform-origin' properties as follows:
368 <ol>
369 <li>Start with the identity matrix.</li>
370 <li>Translate by the computed X, Y and Z values of 'transform-origin'</li>
371 <li>Multiply by each of the transform functions in 'transform' property from left to right</li>
372 <li>Translate by the negated computed X, Y and Z values of 'transform-origin'</li>
373 </ol>
375 <p>
376 Transforms apply to <span class="term">transformable elements</span>.
377 </p>
379 <div class="example">
380 <pre>
381 div {
382 transform: translate(100px, 100px);
383 }
384 </pre>
385 <p>This transform moves the element by 100 pixels in both the X and Y directions.</p>
386 <div class="figure">
387 <img src="examples/translate1.svg" alt="The 100px translation in X and Y"
388 width="470" height="250">
389 </div>
390 </div>
392 <div class="example">
393 <pre>div {
394 height: 100px; width: 100px;
395 transform-origin: 50px 50px;
396 transform: rotate(45deg);
397 }</pre>
399 <p>
400 The 'transform-origin' property moves the point of origin by 50 pixels in both
401 the X and Y directions. The transform rotates the element clockwise by 45Ā° about
402 the point of origin. After all transform functions were applied, the translation
403 of the origin gets translated back by -50 pixels in both the X and Y directions.
404 </p>
406 <div class="figure">
407 <img alt="The point of origin gets translated temporary" src="examples/origin1.svg"
408 width="735" height="250">
409 </div>
410 </div>
412 <div class="example">
413 <pre>
414 div {
415 height: 100px; width: 100px;
416 transform: translate(80px, 80px) scale(1.5, 1.5) rotate(45deg);
417 }
418 </pre>
419 <p>
420 This transform moves the element by 80 pixels in both the X and Y directions, then
421 scales the element by 150%, then rotates it 45° clockwise about the Z axis.
422 Note that the scale and rotation operate about the center of the element, since
423 the element has the default transform-origin of ''50% 50%''.
424 </p>
426 <div class="figure">
427 <img src="examples/compound_transform.svg" alt="The transform specified above"
428 width="270" height="270">
429 </div>
431 <p>
432 Note that an identical rendering can be obtained by nesting elements with the
433 equivalent transforms:
434 </p>
436 <pre>
437 <div style="transform: translate(80px, 80px)">
438 <div style="transform: scale(1.5, 1.5)">
439 <div style="transform: rotate(45deg)"></div>
440 </div>
441 </div></pre>
442 </div>
444 <p>
445 For elements whose layout is governed by the CSS box model, the transform property
446 does not affect the flow of the
447 content surrounding the transformed element. However, the extent of the overflow
448 area takes into account transformed elements. This behavior is similar to what
449 happens when elements are offset via relative positioning. Therefore, if the value
450 of the 'overflow' property is ''scroll'' or ''auto'', scrollbars will appear as
451 needed to see content that is transformed outside the visible area.
452 </p>
453 <p>
454 For elements whose layout is governed by the CSS box model, any value other than
455 ''none'' for the transform results in
456 the creation of both a stacking context and a containing block. The object acts as a
457 containing block for fixed positioned descendants.
458 </p>
459 <p class="issue">
460 Is this effect on position:fixed necessary? If so, need to go into more detail here
461 about why fixed positioned objects should do this, i.e., that it's much harder to
462 implement otherwise. See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328">Bug 16328</a>.
463 </p>
464 <p>
465 <a href="http://www.w3.org/TR/css3-background/#fixed0">Fixed backgrounds</a>
466 on the root element are affected by any transform specified for that element.
467 For all other elements that are effected by a transform (i.e. have a transform
468 applied to them, or to any of their ancestor elements), a value of ''fixed'' for the
469 'background-attachment' property is treated as if it had a value of ''scroll''. The
470 computed value of 'background-attachment' is not affected.
472 <p class="note">
473 If the root element is transformed, the transformation applies
474 to the entire canvas, including any background specified for
475 the root element. Since <a href="http://www.w3.org/TR/css3-background/#special-backgrounds">
476 the background painting area for the root element</a> is the entire
477 canvas, which is infinite, the transformation might cause parts
478 of the background that were originally off-screen to appear.
479 For example, if the root element's background were repeating
480 dots, and a transformation of ''scale(0.5)'' were specified on the
481 root element, the dots would shrink to half their size, but
482 there will be twice as many, so they still cover the whole
483 viewport.
484 </p>
486 <h3 id="transform-3d-rendering">3D Transform Rendering</h3>
488 <p>
489 Normally, elements render as flat planes, and are rendered into the same plane
490 as their containing block. Often this is the plane shared by the rest of the page.
491 Two-dimensional transform functions can alter the appearance of an element, but
492 that element is still rendered into the same plane as its containing block.
493 </p>
494 <p>
495 Three-dimensional transforms can result in transformation matrices with a non-zero
496 Z component (where the Z axis projects out of the plane of the screen). This can result
497 in an element rendering on a different plane than that of its containing block. This
498 may affect the front-to-back rendering order of that element relative to other elements,
499 as well as causing it to intersect with other elements. This behavior depends on whether the
500 element is a member of a <span class="term">3D rendering context</span>, as described below.
501 </p>
502 <div class="issue">
503 <p class="desc">This description does not exactly match what WebKit implements. Perhaps
504 it should be changed to match current implementations? See
505 <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=19637">Bug 19637</a>.</p>
506 </div>
508 <div class="example">
509 <p>This example shows the effect of three-dimensional transform applied to an element.
510 </p>
511 <pre>
512 <style>
513 div {
514 height: 150px;
515 width: 150px;
516 }
517 .container {
518 border: 1px solid black;
519 }
520 .transformed {
521 transform: rotateY(50deg);
522 }
523 </style>
525 <div class="container">
526 <div class="transformed"></div>
527 </div>
528 </pre>
529 <div class="figure">
530 <img src="examples/simple-3d-example.png" width="210" height="190" alt="Div with a rotateY transform.">
531 </div>
532 <p>The transform is a 50° rotation about the vertical, Y axis. Note how this makes the blue box appear
533 narrower, but not three-dimensional.
534 </p>
535 </div>
537 <p>
538 The 'perspective' and 'perspective-origin' properties can be used to add a feeling
539 of depth to a scene by making elements higher on the Z axis (closer to the viewer)
540 appear larger, and those further away to appear smaller. The scaling is proportional
541 to <var>d</var>/(<var>d</var> − <var>Z</var>) where <var>d</var>, the value of
542 'perspective', is the distance from the drawing plane to the the assumed position of
543 the viewer's eye.
544 </p>
546 <div class="figure">
547 <img alt="Diagram of scale vs. Z position" src="perspective_distance.png">
548 <p class="caption">
549 Diagrams showing how scaling depends on the 'perspective' property and Z position.
550 In the top diagram, <var>Z</var> is half of <var>d</var>. In order to make it
551 appear that the original circle (solid outline) appears at <var>Z</var> (dashed
552 circle), the circle is scaled up by a factor of two, resulting in the light blue
553 circle. In the bottom diagram, the circle is scaled down by a factor of one-third
554 to make it appear behind the original position.
555 </p>
556 </div>
558 <p>
559 Normally the assumed position of the viewer's eye is
560 centered on a drawing. This position can be moved if
561 desired – for example, if a web page contains
562 multiple drawings that should share a common perspective
563 – by setting 'perspective-origin'.
564 </p>
566 <div class="figure">
567 <img alt="Diagram of different perspective-origin" src="perspective_origin.png">
568 <p class="caption">
569 Diagram showing the effect of moving the perspective origin upward.
570 </p>
571 </div>
573 <p id="perspective-matrix-computation">
574 The <a href="#TermPerspectiveMatrix"><i>perspective matrix</i></a> is computed as follows:
575 <ol>
576 <li>Start with the identity matrix.</li>
577 <li>Translate by the computed X and Y values of 'perspective-origin'</li>
578 <li>Multiply by the matrix that would be obtained from the '<a href="#perspective-function"><code class="css">perspective(<length>)</code></a>' transform function, where the length is provided by the value of the 'perspective' property</li>
579 <li>Translate by the negated computed X and Y values of 'perspective-origin'</li>
580 </ol>
583 <div class="example">
584 <p>This example shows how perspective can be used to cause three-dimensional transforms to appear more realistic.
585 </p>
586 <pre>
587 <style>
588 div {
589 height: 150px;
590 width: 150px;
591 }
592 .container {
593 perspective: 500px;
594 border: 1px solid black;
595 }
596 .transformed {
597 transform: rotateY(50deg);
598 }
599 </style>
601 <div class="container">
602 <div class="transformed"></div>
603 </div>
604 </pre>
605 <div class="figure">
606 <img src="examples/simple-perspective-example.png" width="210" height="190" alt="Div with a rotateY transform,
607 and perspective on its container">
608 </div>
609 <p>The inner element has the same transform as in the previous example, but its rendering is now influenced by the perspective
610 property on its parent element. Perspective causes vertices that have positive Z coordinates (closer to the viewer)
611 to be scaled up in X and Y, and those further away (negative Z coordinates) to be scaled down, giving an appearance of depth.
612 </p>
613 </div>
615 <p>
616 An element with a three-dimensional transform that is not contained in a
617 <span class="term">3D rendering context</span> renders with the appropriate
618 transform applied, but does not intersect with any other elements. The three-dimensional
619 transform in this case can be considered just as a painting effect, like two-dimensional
620 transforms. Similarly, the transform does not affect painting order. For example, a transform with a
621 positive Z translation may make an element look larger, but does not cause that element
622 to render in front of elements with no translation in Z.
623 </p>
624 <p>
625 An element with a three-dimensional transform that is contained in a
626 <span class="term">3D rendering context</span> can visibly interact with other elements
627 in that same 3D rendering context; the set of elements participating in the same
628 <span class="term">3D rendering context</span> may obscure each other or intersect,
629 based on their computed transforms. They are rendered as if they are all siblings,
630 positioned in a common 3D coordinate space. The position of each element in that three-dimensional
631 space is determined by accumulating the transformation matrices
632 up from the element that establishes the <span class="term">3D rendering context</span>
633 through each element that is a containing block for the given element, as described below.
634 </p>
636 <div class="example">
637 <pre>
638 <style>
639 div {
640 height: 150px;
641 width: 150px;
642 }
643 .container {
644 perspective: 500px;
645 border: 1px solid black;
646 }
647 .transformed {
648 transform: rotateY(50deg);
649 background-color: blue;
650 }
651 .child {
652 transform-origin: top left;
653 transform: rotateX(40deg);
654 background-color: lime;
655 }
656 </style>
658 <div class="container">
659 <div class="transformed">
660 <div class="child"></div>
661 </div>
662 </div>
663 </pre>
664 <p>This example shows how nested 3D transforms are rendered in the absence of ''transform-style: preserve-3d''. The blue div is transformed as in the previous example, with its rendering influenced by the perspective on its parent element. The lime element also has a 3D transform, which is a rotation about the X axis (anchored at the top, by virtue of the transform-origin). However, the lime element is being rendered into the plane of its parent because it is not a member of a 3D rendering context; the parent is "flattening".
665 </p>
666 <div class="figure">
667 <img src="examples/3d-rendering-context-flat.png" width="240" height="200" alt="Nested 3D transforms, with flattening">
668 </div>
669 </div>
671 <p>Elements establish and participate in 3D rendering contexts as follows:</p>
672 <ul>
673 <li>
674 A <span class="term">3D rendering context</span> is established by a
675 a <span class="term">transformable element</span> whose computed value for 'transform-style' is
676 ''preserve-3d'', and which itself is not part of a 3D rendering context.
677 Note that such an element is always a containing block. An element that establishes a 3D rendering context
678 also participates in that context.
679 </li>
680 <li>
681 An element whose computed value for 'transform-style' is
682 ''preserve-3d'', and which itself participates in a
683 <span class="term">3D rendering context</span>, extends that 3D rendering context rather than establishing
684 a new one.
685 </li>
686 <li>
687 An element participates in a <span class="term">3D rendering context</span> if its containing block
688 establishes or extends a <span class="term">3D rendering context</span>.
689 </li>
690 </ul>
691 <p id="accumulated-3d-transformation-matrix-computation">
692 The final value of the transform used to render an element in a <span class="term">3D rendering context</span>
693 is computed by accumulating an
694 <a href="#TermAccumulated3DTransformationMatrix">
695 accumulated 3D transformation matrix</a> as follows:
696 </p>
697 <ol>
698 <li>Start with the identity matrix.</li>
699 <li>For each containing block between the root of the <span class="term">3D rendering context</span>
700 and the element in question:
701 <ol>
702 <li>multiply the accumulated matrix with the <span class="term">perspective matrix</span>
703 on the element's containing block (if any). That containing block is not necessarily a member
704 of the 3D rendering context.</li>
705 <li>apply to the accumulated matrix a translation equivalent to the horizontal and vertical offset of the element relative to
706 its containing block as specified by the CSS visual formatting model.</li>
707 <li>multiply the accumulated matrix with the <span class="term">transformation matrix</span>.</li>
708 </ol>
709 </li>
710 </ol>
712 <div class="example">
713 <pre>
714 <style>
715 div {
716 height: 150px;
717 width: 150px;
718 }
719 .container {
720 perspective: 500px;
721 border: 1px solid black;
722 }
723 .transformed {
724 <b>transform-style: preserve-3d</b>;
725 transform: rotateY(50deg);
726 background-color: blue;
727 }
728 .child {
729 transform-origin: top left;
730 transform: rotateX(40deg);
731 background-color: lime;
732 }
733 </style>
734 </pre>
735 <p>
736 This example is identical to the previous example, with the addition of
737 ''transform-style: preserve-3d'' on the blue element. The blue element now
738 establishes a 3D rendering context, of which the lime element is a member. Now
739 both blue and lime elements share a common three-dimensional space, so the lime
740 element renders as tilting out from its parent, influenced by the perspective on
741 the container.
742 </p>
743 <div class="figure">
744 <img src="examples/3d-rendering-context-3d.png" width="240" height="200" alt="Nested 3D transforms, with preserve-3d.">
745 </div>
746 </div>
748 <p>
749 Elements in the same <span class="term">3D rendering context</span> may intersect with each other. User agents must
750 render intersection by subdividing the planes of intersecting elements as described by
751 <a href="http://en.wikipedia.org/wiki/Newell's_algorithm">Newell's algorithm</a>.
752 </p>
753 <p>
754 Untransformed elements in a <span class="term">3D rendering context</span> render on the Z=0 plane, yet may still
755 intersect with transformed elements.
756 </p>
757 <p>
758 Within a <span class="term">3D rendering context</span>, the rendering order of non-intersecting elements is
759 based on their position on the Z axis after the application of the accumulated transform. Elements at the same
760 Z position render in <a href="http://www.w3.org/TR/CSS2/zindex.html#painting-order">stacking context order</a>.
761 </p>
763 <div class="example">
764 <pre>
765 <style>
766 .container {
767 background-color: rgba(0, 0, 0, 0.3);
768 transform-style: preserve-3d;
769 perspective: 500px;
770 }
771 .container > div {
772 position: absolute;
773 left: 0;
774 }
775 .container > :first-child {
776 transform: rotateY(45deg);
777 background-color: orange;
778 top: 10px;
779 height: 135px;
780 }
781 .container > :last-child {
782 transform: translateZ(40px);
783 background-color: rgba(0, 0, 255, 0.75);
784 top: 50px;
785 height: 100px;
786 }
787 </style>
789 <div class="container">
790 <div></div>
791 <div></div>
792 </div>
793 </pre>
794 <p>
795 This example shows show elements in a 3D rendering context can intersect. The container element establishes
796 a 3D rendering context for itself and its two children. The children intersect with eachother, and
797 the orange element also intersects with the container.
798 </p>
799 <div class="figure">
800 <img src="examples/3d-intersection.png" width="200" height="200" alt="Intersecting sibling elements.">
801 </div>
802 </div>
804 <p>
805 Using three-dimensional transforms, it's possible to transform an element such that its reverse side
806 is towards the viewer. 3D-transformed elements show the same content on both sides, so the reverse side
807 looks like a mirror-image of the front side (as if the element were projected onto a sheet of glass).
808 Normally, elements whose reverse side is towards the viewer remain visible. However, the
809 'backface-visibility' property allows the author to make an element invisible
810 when its reverse side is towards the viewer. This behavior is "live"; if an element with
811 ''backface-visibility: hidden'' were animating,
812 such that its front and reverse sides were alternately visible, then it would only be visible when the
813 front side were towards the viewer.
814 </p>
816 <h3 id="processing-of-perspective-transformed-boxes">
817 Processing of Perspective-Transformed Boxes
818 </h3>
820 <div class="issue">
821 <p class="desc">
822 This is a first pass at an attempt to precisely specify how
823 exactly to transform elements using the provided matrices.
824 It might not be ideal, and implementer feedback is
825 encouraged. See <a
826 href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=15605">bug
827 15605</a>.
828 </p>
829 </div>
831 <p>
832 The <span class="term">accumulated
833 3D transformation matrix</span> is a 4×4 matrix, while the
834 objects to be transformed are two-dimensional boxes. To
835 transform each corner (<var>a</var>, <var>b</var>) of a box, the
836 matrix must first be applied to (<var>a</var>, <var>b</var>, 0,
837 1), which will result in a four-dimensional point (<var>x</var>,
838 <var>y</var>, <var>z</var>, <var>w</var>). This is transformed
839 back to a three-dimensional point (<var>x</var>′, <var>y</var>′,
840 <var>z</var>′) as follows:
841 </p>
843 <p>
844 If <var>w</var> > 0, (<var>x</var>′,
845 <var>y</var>′, <var>z</var>′) =
846 (<var>x</var>/<var>w</var>, <var>y</var>/<var>w</var>,
847 <var>z</var>/<var>w</var>).
848 </p>
850 <p>
851 If <var>w</var> = 0, (<var>x</var>′, <var>y</var>′,
852 <var>z</var>′) = (<var>x</var> ⋅ <var>n</var>,
853 <var>y</var> ⋅ <var>n</var>, <var>z</var> ⋅
854 <var>n</var>). <var>n</var> is an implementation-dependent value
855 that should be chosen so that <var>x</var>′ or
856 <var>y</var>′ is much larger than the viewport size, if
857 possible. For example, (5px, 22px, 0px, 0) might become (5000px,
858 22000px, 0px), with <var>n</var> = 1000, but this value of
859 <var>n</var> would be too small for (0.1px, 0.05px, 0px, 0).
860 This specification does not define the value of <var>n</var>
861 exactly. Conceptually, (<var>x</var>′,
862 <var>y</var>′, <var>z</var>′) is <a
863 href="http://en.wikipedia.org/wiki/Plane_at_infinity">infinitely
864 far</a> in the direction (<var>x</var>, <var>y</var>,
865 <var>z</var>).
866 </p>
868 <p>
869 If <var>w</var> < 0 for all four corners of the transformed
870 box, the box is not rendered.
871 </p>
873 <p>
874 If <var>w</var> < 0 for one to three corners of the
875 transformed box, the box must be replaced by a polygon that has
876 any parts with <var>w</var> < 0 cut out. This will in general
877 be a polygon with three to five vertices, of which exactly two
878 will have <var>w</var> = 0 and the rest <var>w</var> > 0.
879 These vertices are then transformed to three-dimensional points
880 using the rules just stated. Conceptually, a point with
881 <var>w</var> < 0 is "behind" the viewer, so should not be
882 visible.
883 </p>
885 <div class="example">
886 <pre><style>
887 .transformed {
888 height: 100px;
889 width: 100px;
890 background: lime;
891 transform: perspective(50px) translateZ(100px);
892 }
893 </style></pre>
895 <p>
896 All of the box's corners have <var>z</var>-coordinates greater
897 than the perspective. This means that the box is behind the
898 viewer and will not display. Mathematically, the point
899 (<var>x</var>, <var>y</var>) first becomes (<var>x</var>,
900 <var>y</var>, 0, 1), then is translated to (<var>x</var>,
901 <var>y</var>, 100, 1), and then applying the perspective
902 results in (<var>x</var>, <var>y</var>, 100, −1). The
903 <var>w</var>-coordinate is negative, so it does not display.
904 An implementation that doesn't handle the <var>w</var> < 0
905 case separately might incorrectly display this point as
906 (−<var>x</var>, −<var>y</var>, −100),
907 dividing by −1 and mirroring the box.
908 </p>
909 </div>
911 <div class="example">
912 <pre><style>
913 .transformed {
914 height: 100px;
915 width: 100px;
916 background: radial-gradient(yellow, blue);
917 transform: perspective(50px) translateZ(50px);
918 }
919 </style></pre>
921 <p>
922 Here, the box is translated upward so that it sits at the same
923 place the viewer is looking from. This is like bringing the
924 box closer and closer to one's eye until it fills the entire
925 field of vision. Since the default transform-origin is at the
926 center of the box, which is yellow, the screen will be filled
927 with yellow.
928 </p>
930 <p>
931 Mathematically, the point (<var>x</var>, <var>y</var>) first
932 becomes (<var>x</var>, <var>y</var>, 0, 1), then is translated
933 to (<var>x</var>, <var>y</var>, 50, 1), then becomes
934 (<var>x</var>, <var>y</var>, 50, 0) after applying perspective.
935 Relative to the transform-origin at the center, the upper-left
936 corner was (−50, −50), so it becomes (−50,
937 −50, 50, 0). This is transformed to something
938 very far to the upper left, such as (−5000, −5000,
939 5000). Likewise the other corners are sent very far away. The
940 radial gradient is stretched over the whole box, now enormous,
941 so the part that's visible without scrolling should be the
942 color of the middle pixel: yellow. However, since the box is
943 not actually infinite, the user can still scroll to the edges
944 to see the blue parts.
945 </p>
946 </div>
948 <div class="example">
949 <pre><style>
950 .transformed {
951 height: 50px;
952 width: 50px;
953 background: lime;
954 border: 25px solid blue;
955 transform-origin: left;
956 transform: perspective(50px) rotateY(-45deg);
957 }
958 </style></pre>
960 <p>
961 The box will be rotated toward the viewer, with the left edge
962 staying fixed while the right edge swings closer. The right
963 edge will be at about <var>z</var> = 70.7px, which is closer
964 than the perspective of 50px. Therefore, the rightmost edge
965 will vanish ("behind" the viewer), and the visible part will
966 stretch out infinitely far to the right.
967 </p>
969 <p>
970 Mathematically, the top right vertex of the box was originally
971 (100, −50), relative to the transform-origin. It is first
972 expanded to (100, −50, 0, 1). After applying the
973 transform specified, this will get mapped to about (70.71,
974 −50, 70.71, −0.4142). This has <var>w</var> =
975 −0.4142 < 0, so we need to slice away the part of the
976 box with <var>w</var> < 0. This results in the new
977 top-right vertex being (50, −50, 50, 0). This is then
978 mapped to some faraway point in the same direction, such as
979 (5000, −5000, 5000), which is up and to the right from
980 the transform-origin. Something similar is done to the lower
981 right corner, which gets mapped far down and to the right. The
982 resulting box stretches far past the edge of the screen.
983 </p>
985 <p>
986 Again, the rendered box is still finite, so the user can scroll
987 to see the whole thing if he or she chooses. However, the
988 right part has been chopped off. No matter how far the user
989 scrolls, the rightmost 30px or so of the original box will not
990 be visible. The blue border was only 25px wide, so it will be
991 visible on the left, top, and bottom, but not the right.
992 </p>
994 <p>
995 The same basic procedure would apply if one or three vertices
996 had <var>w</var> < 0. However, in that case the result of
997 truncating the <var>w</var> < 0 part would be a triangle or
998 pentagon instead of a quadrilateral.
999 </p>
1000 </div>
1002 <!-- ======================================================================================================= -->
1004 <h2 id="transform-property">
1005 The 'transform' Property
1006 </h2>
1007 <p>
1008 A transformation is applied to the coordinate system an element
1009 renders in through the 'transform' property. This property contains a
1010 list of <a href="#transform-functions">transform functions</a>. The
1011 final transformation value for a coordinate system is obtained by converting
1012 each function in the list to its corresponding matrix like defined in <a
1013 href="#mathematical-description">Mathematical Description of Transform
1014 Functions</a>, then multiplying the matrices.
1015 </p>
1016 <table class="propdef">
1017 <tbody>
1018 <tr>
1019 <td>
1020 <em>Name:</em>
1021 </td>
1022 <td>
1023 <dfn id="effects">transform</dfn>
1024 </td>
1025 </tr>
1026 <tr>
1027 <td>
1028 <em>Value:</em>
1029 </td>
1030 <td>
1031 none | <transform-function> [ <transform-function> ]*
1032 </td>
1033 </tr>
1034 <tr>
1035 <td>
1036 <em>Initial:</em>
1037 </td>
1038 <td>
1039 none
1040 </td>
1041 </tr>
1042 <tr>
1043 <td>
1044 <em>Applies to:</em>
1045 </td>
1046 <td>
1047 <a href="#TermTransformableElement">transformable elements</a>
1048 </td>
1049 </tr>
1050 <tr>
1051 <td>
1052 <em>Inherited:</em>
1053 </td>
1054 <td>
1055 no
1056 </td>
1057 </tr>
1058 <tr>
1059 <td>
1060 <em>Percentages:</em>
1061 </td>
1062 <td>
1063 refer to the size of
1064 <var>bounding box</var>
1065 </td>
1066 </tr>
1067 <tr>
1068 <td>
1069 <em>Media:</em>
1070 </td>
1071 <td>
1072 visual
1073 </td>
1074 </tr>
1075 <tr>
1076 <td>
1077 <em>Computed value:</em>
1078 </td>
1079 <td>
1080 As specified, but with relative lengths converted into
1081 absolute lengths.
1082 </td>
1083 </tr>
1084 <tr>
1085 <td>
1086 <em>Animatable:</em>
1087 </td>
1088 <td>
1089 as <a href="#animation">transform</a>
1090 </td>
1091 </tr>
1092 </tbody>
1093 </table>
1095 <p>
1096 Any value other than ''none'' for the transform results in the creation of both a
1097 stacking context and a containing block. The object acts as a containing block for
1098 fixed positioned descendants.
1099 </p>
1101 <!-- ======================================================================================================= -->
1103 <h2 id="transform-origin-property">
1104 The 'transform-origin' Property
1105 </h2>
1106 <table class="propdef">
1107 <tbody>
1108 <tr>
1109 <td>
1110 <em>Name:</em>
1111 </td>
1112 <td>
1113 <dfn id="transform-origin">transform-origin</dfn>
1114 </td>
1115 </tr>
1116 <tr>
1117 <td>
1118 <em>Value:</em>
1119 </td>
1120 <td>
1121 [ left | center | right | top | bottom | <var><percentage></var> | <var><length></var> ]<br>
1122 |<br>
1123 [ left | center | right | <var><percentage></var> | <var><length></var> ]<br>
1124 [ top | center | bottom | <var><percentage></var> | <var><length></var> ] <var><length></var>?
1125 </td>
1126 </tr>
1127 <tr>
1128 <td>
1129 <em>Initial:</em>
1130 </td>
1131 <td>
1132 50% 50%
1133 </td>
1134 </tr>
1135 <tr>
1136 <td>
1137 <em>Applies to:</em>
1138 </td>
1139 <td>
1140 <a href="#TermTransformableElement">transformable elements</a>
1141 </td>
1142 </tr>
1143 <tr>
1144 <td>
1145 <em>Inherited:</em>
1146 </td>
1147 <td>
1148 no
1149 </td>
1150 </tr>
1151 <tr>
1152 <td>
1153 <em>Percentages:</em>
1154 </td>
1155 <td>
1156 refer to the size of
1157 <var>bounding box</var>
1158 </td>
1159 </tr>
1160 <tr>
1161 <td>
1162 <em>Media:</em>
1163 </td>
1164 <td>
1165 visual
1166 </td>
1167 </tr>
1168 <tr>
1169 <td>
1170 <em>Computed value:</em>
1171 </td>
1172 <td>
1173 For <length> the absolute value, otherwise a percentage
1174 </td>
1175 </tr>
1176 <tr>
1177 <td>
1178 <em>Animatable:</em>
1179 </td>
1180 <td>
1181 as <a href="http://dev.w3.org/csswg/css3-transitions/#animtype-simple-list">simple list</a> of <a href="http://dev.w3.org/csswg/css3-transitions/#animtype-lpcalc">length, percentage, or calc</a>
1182 </td>
1183 </tr>
1184 </tbody>
1185 </table>
1187 <p>
1188 The default value for SVG elements without associated CSS layout box is ''0 0''.
1189 </p>
1191 <p>
1192 The values of the 'transform' and 'transform-origin' properties are used to compute
1193 the <span class="term">transformation matrix</span>, as
1194 described above.
1195 </p>
1197 <p>
1198 If only one value is specified, the second value is assumed to be ''center''. If one
1199 or two values are specified, the third value is assumed to be ''0px''.
1200 </p>
1202 <p>
1203 If two or more values are defined and either no value is a keyword, or the only
1204 used keyword is ''center'', then the first value represents the horizontal position
1205 (or offset) and the second represents the vertical position (or offset). A third
1206 value always represents the Z position (or offset) and must be of type
1207 <var><length></var>.
1208 </p>
1210 <dl>
1211 <dt><var><percentage></var>
1213 <dd><p>A percentage for the horizontal offset is relative to the width of the
1214 <var>bounding box</var>.
1215 A percentage for the vertical offset is relative to height of the
1216 <var>bounding box</var>. The value for the horizontal
1217 and vertical offset represent an offset from the top left corner of the
1218 <var>bounding box</var>.
1219 </p>
1221 <dt><var><length></var>
1223 <dd>
1224 <p>A length value gives a fixed length as the offset. The value for the horizontal
1225 and vertical offset represent an offset from the top left corner of the
1226 <var>bounding box</var>.
1227 </p>
1229 <p>For SVG elements without an associated CSS layout box the horizontal
1230 and vertical offset represent an offset from the point of origin of
1231 the element's local coordinate space.
1232 </p>
1233 </dd>
1235 <dt><dfn title="''top''!!'transform-origin' value">''top''</dfn>
1237 <dd>Computes to ''0%'' for the vertical position.
1239 <dt><dfn title="''right''!!'transform-origin' value">''right''</dfn>
1241 <dd>Computes to ''100%'' for the horizontal position.
1243 <dt><dfn title="''bottom''!!'transform-origin' value">''bottom''</dfn>
1245 <dd>Computes to ''100%'' for the vertical position.
1247 <dt><dfn title="''left''!!'transform-origin' value">''left''</dfn>
1249 <dd>Computes to ''0%'' for the horizontal position.
1251 <dt><dfn title="''center''!!'transform-origin' value">''center''</dfn>
1253 <dd>Computes to ''50%'' (''left 50%'') for the
1254 horizontal position if the horizontal position is not otherwise
1255 specified, or ''50%'' (''top 50%'') for the vertical position if
1256 it is.
1257 </dl>
1259 <p>
1260 The <a href="http://www.w3.org/TR/cssom/#resolved-value">resolved value</a>
1261 of 'transform-origin' is the
1262 <a href="http://www.w3.org/TR/CSS21/cascade.html#used-value">used value</a>
1263 (i.e., percentages are resolved to absolute lengths).
1264 </p>
1266 <!-- ======================================================================================================= -->
1268 <h2 id="transform-style-property">
1269 The 'transform-style' Property
1270 </h2>
1271 <table class="propdef">
1272 <tbody>
1273 <tr>
1274 <td>
1275 <em>Name:</em>
1276 </td>
1277 <td>
1278 <dfn id="transform-style">transform-style</dfn>
1279 </td>
1280 </tr>
1281 <tr>
1282 <td>
1283 <em>Value:</em>
1284 </td>
1285 <td>
1286 flat | preserve-3d
1287 </td>
1288 </tr>
1289 <tr>
1290 <td>
1291 <em>Initial:</em>
1292 </td>
1293 <td>
1294 flat
1295 </td>
1296 </tr>
1297 <tr>
1298 <td>
1299 <em>Applies to:</em>
1300 </td>
1301 <td>
1302 <a href="#TermTransformableElement">transformable elements</a>
1303 </td>
1304 </tr>
1305 <tr>
1306 <td>
1307 <em>Inherited:</em>
1308 </td>
1309 <td>
1310 no
1311 </td>
1312 </tr>
1313 <tr>
1314 <td>
1315 <em>Percentages:</em>
1316 </td>
1317 <td>
1318 N/A
1319 </td>
1320 </tr>
1321 <tr>
1322 <td>
1323 <em>Media:</em>
1324 </td>
1325 <td>
1326 visual
1327 </td>
1328 </tr>
1329 <tr>
1330 <td>
1331 <em>Computed value:</em>
1332 </td>
1333 <td>
1334 Same as specified value.
1335 </td>
1336 </tr>
1337 <tr>
1338 <td>
1339 <em>Animatable:</em>
1340 </td>
1341 <td>
1342 no
1343 </td>
1344 </tr>
1345 </tbody>
1346 </table>
1348 <p>
1349 A value of ''preserve-3d'' for 'transform-style' establishes a stacking context.
1350 </p>
1352 <p>
1353 The following CSS property values require the user agent to create a flattened representation of
1354 the descendant elements before they can be applied, and therefore override the behavior of
1355 ''transform-style: preserve-3d'':</p>
1356 <ul>
1357 <li>'overflow': any value other than ''visible''.</li>
1358 <li>'opacity': any value other than ''1''.</li>
1359 <li>'filter': any value other than ''none''.</li>
1360 </ul>
1362 <p>
1363 The computed value of 'transform-style' is not affected.
1364 </p>
1366 <p>
1367 The values of the 'transform' and 'transform-origin' properties are used to compute
1368 the <span class="term">transformation matrix</span>, as described above.
1369 </p>
1371 <!-- ======================================================================================================= -->
1373 <h2 id="perspective-property">
1374 The 'perspective' Property
1375 </h2>
1376 <table class="propdef">
1377 <tbody>
1378 <tr>
1379 <td>
1380 <em>Name:</em>
1381 </td>
1382 <td>
1383 <dfn id="perspective">perspective</dfn>
1384 </td>
1385 </tr>
1386 <tr>
1387 <td>
1388 <em>Value:</em>
1389 </td>
1390 <td>
1391 none | <length>
1392 </td>
1393 </tr>
1394 <tr>
1395 <td>
1396 <em>Initial:</em>
1397 </td>
1398 <td>
1399 none
1400 </td>
1401 </tr>
1402 <tr>
1403 <td>
1404 <em>Applies to:</em>
1405 </td>
1406 <td>
1407 <a href="#TermTransformableElement">transformable elements</a>
1408 </td>
1409 </tr>
1410 <tr>
1411 <td>
1412 <em>Inherited:</em>
1413 </td>
1414 <td>
1415 no
1416 </td>
1417 </tr>
1418 <tr>
1419 <td>
1420 <em>Percentages:</em>
1421 </td>
1422 <td>
1423 N/A
1424 </td>
1425 </tr>
1426 <tr>
1427 <td>
1428 <em>Media:</em>
1429 </td>
1430 <td>
1431 visual
1432 </td>
1433 </tr>
1434 <tr>
1435 <td>
1436 <em>Computed value:</em>
1437 </td>
1438 <td>
1439 Absolute length or "none".
1440 </td>
1441 </tr>
1442 <tr>
1443 <td>
1444 <em>Animatable:</em>
1445 </td>
1446 <td>
1447 as <a href="http://dev.w3.org/csswg/css3-transitions/#animtype-length">length</a>
1448 </td>
1449 </tr>
1450 </tbody>
1451 </table>
1453 <p>
1454 If the value is ''none'', no perspective
1455 transform is applied. Lengths must be positive.
1456 </p>
1457 <p>
1458 The use of this property with any value other than ''none'' establishes a
1459 stacking context. It also establishes a containing block (somewhat
1460 similar to ''position: relative''), just like the 'transform' property does.
1461 </p>
1462 <p>
1463 The values of the 'perspective' and 'perspective-origin' properties are used to
1464 compute the <span class="term">perspective matrix</span>, as described above.
1465 </p>
1467 <!-- ======================================================================================================= -->
1469 <h2 id="perspective-origin-property">
1470 The 'perspective-origin' Property
1471 </h2>
1472 <p>
1473 The 'perspective-origin' property establishes the origin for the
1474 <em>perspective</em> property. It effectively sets the X and Y position at which the
1475 viewer appears to be looking at the children of the element.
1476 </p>
1477 <table class="propdef">
1478 <tbody>
1479 <tr>
1480 <td>
1481 <em>Name:</em>
1482 </td>
1483 <td>
1484 <dfn id="perspective-origin">perspective-origin</dfn>
1485 </td>
1486 </tr>
1487 <tr>
1488 <td>
1489 <em>Value:</em>
1490 </td>
1491 <td>
1492 [ left | center | right | top | bottom | <var><percentage></var> | <var><length></var> ]<br>
1493 |<br>
1494 [ left | center | right | <var><percentage></var> | <var><length></var> ]<br>
1495 [ top | center | bottom | <var><percentage></var> | <var><length></var> ]
1496 </td>
1497 </tr>
1498 <tr>
1499 <td>
1500 <em>Initial:</em>
1501 </td>
1502 <td>
1503 50% 50%
1504 </td>
1505 </tr>
1506 <tr>
1507 <td>
1508 <em>Applies to:</em>
1509 </td>
1510 <td>
1511 <a href="#TermTransformableElement">transformable elements</a>
1512 </td>
1513 </tr>
1514 <tr>
1515 <td>
1516 <em>Inherited:</em>
1517 </td>
1518 <td>
1519 no
1520 </td>
1521 </tr>
1522 <tr>
1523 <td>
1524 <em>Percentages:</em>
1525 </td>
1526 <td>
1527 refer to the size of the
1528 <var>bounding box</var>
1529 </td>
1530 </tr>
1531 <tr>
1532 <td>
1533 <em>Media:</em>
1534 </td>
1535 <td>
1536 visual
1537 </td>
1538 </tr>
1539 <tr>
1540 <td>
1541 <em>Computed value:</em>
1542 </td>
1543 <td>
1544 For <length> the absolute value, otherwise a
1545 percentage.
1546 </td>
1547 </tr>
1548 <tr>
1549 <td>
1550 <em>Animatable:</em>
1551 </td>
1552 <td>
1553 as <a href="http://dev.w3.org/csswg/css3-transitions/#animtype-simple-list">simple list</a> of <a href="http://dev.w3.org/csswg/css3-transitions/#animtype-lpcalc">length, percentage, or calc</a>
1554 </td>
1555 </tr>
1556 </tbody>
1557 </table>
1558 <p>
1559 The values of the 'perspective' and 'perspective-origin' properties are used to
1560 compute the <span class="term">perspective matrix</span>, as described above.
1561 </p>
1563 <p>
1564 If only one value is specified, the second value is assumed to be ''center''.
1565 </p>
1567 <p>
1568 If at least one of the two values is not a keyword, then the
1569 first value represents the horizontal position (or offset) and
1570 the second represents the vertical position (or offset).
1571 </p>
1573 <p>
1574 The values for 'perspective-origin' represent an offset of the perspective origin
1575 from the top
1576 left corner of the <var>bounding box</var>.
1577 </p>
1579 <dl>
1580 <dt><var><percentage></var>
1582 <dd><p>A percentage for the horizontal perspctive offset is relative to the width of the
1583 <var>bounding box</var>.
1584 A percentage for the vertical offset is relative to height of the
1585 <var>bounding box</var>. The value for the horizontal
1586 and vertical offset represent an offset from the top left corner of the
1587 <var>bounding box</var>.
1588 </p>
1590 <dt><var><length></var>
1592 <dd>
1593 <p>A length value gives a fixed length as the offset. The value for the horizontal
1594 and vertical offset represent an offset from the top left corner of the
1595 <var>bounding box</var>.
1596 </dd>
1598 <dt><dfn title="''top''!!'perspective-origin' value">''top''</dfn>
1600 <dd>Computes to ''0%'' for the vertical position.
1602 <dt><dfn title="''right''!!'perspective-origin' value">''right''</dfn>
1604 <dd>Computes to ''100%'' for the horizontal position.
1606 <dt><dfn title="''bottom''!!'perspective-origin' value">''bottom''</dfn>
1608 <dd>Computes to ''100%'' for the vertical position.
1610 <dt><dfn title="''left''!!'perspective-origin' value">''left''</dfn>
1612 <dd>Computes to ''0%'' for the horizontal position.
1614 <dt><dfn title="''center''!!'perspective-origin' value">''center''</dfn>
1616 <dd>Computes to ''50%'' (''left 50%'') for the
1617 horizontal position if the horizontal position is not otherwise
1618 specified, or ''50%'' (''top 50%'') for the vertical position if
1619 it is.
1620 </dl>
1622 <p>
1623 The <a href="http://www.w3.org/TR/cssom/#resolved-value">resolved value</a>
1624 of 'perspective-origin' is the
1625 <a href="http://www.w3.org/TR/CSS21/cascade.html#used-value">used value</a>
1626 (i.e., percentages are resolved to absolute lengths).
1627 </p>
1629 <!-- ======================================================================================================= -->
1631 <h2 id="backface-visibility-property">
1632 The 'backface-visibility' Property
1633 </h2>
1634 <p>
1635 The 'backface-visibility' property
1636 determines whether or not the "back" side of a transformed element is
1637 visible when facing the viewer. With an identity transform, the front
1638 side of an element faces the viewer. Applying a rotation about Y of 180
1639 degrees (for instance) would cause the back side of the element to face
1640 the viewer.
1641 </p>
1642 <p class="note">
1643 Note that this property is useful when you place two elements back-to-back, as you
1644 would to create a playing card. Without this property, the front and
1645 back elements could switch places at times during an animation to flip
1646 the card. Another example is creating a box out of 6 elements, but where
1647 you want to see the inside faces of the box. This is useful when
1648 creating the backdrop for a 3 dimensional stage.
1649 </p>
1650 <table class="propdef">
1651 <tbody>
1652 <tr>
1653 <td>
1654 <em>Name:</em>
1655 </td>
1656 <td>
1657 <dfn id="backface-visibility">backface-visibility</dfn>
1658 </td>
1659 </tr>
1660 <tr>
1661 <td>
1662 <em>Value:</em>
1663 </td>
1664 <td>
1665 visible | hidden
1666 </td>
1667 </tr>
1668 <tr>
1669 <td>
1670 <em>Initial:</em>
1671 </td>
1672 <td>
1673 visible
1674 </td>
1675 </tr>
1676 <tr>
1677 <td>
1678 <em>Applies to:</em>
1679 </td>
1680 <td>
1681 <a href="#TermTransformableElement">transformable elements</a>
1682 </td>
1683 </tr>
1684 <tr>
1685 <td>
1686 <em>Inherited:</em>
1687 </td>
1688 <td>
1689 no
1690 </td>
1691 </tr>
1692 <tr>
1693 <td>
1694 <em>Percentages:</em>
1695 </td>
1696 <td>
1697 N/A
1698 </td>
1699 </tr>
1700 <tr>
1701 <td>
1702 <em>Media:</em>
1703 </td>
1704 <td>
1705 visual
1706 </td>
1707 </tr>
1708 <tr>
1709 <td>
1710 <em>Computed value:</em>
1711 </td>
1712 <td>
1713 Same as specified value.
1714 </td>
1715 </tr>
1716 <tr>
1717 <td>
1718 <em>Animatable:</em>
1719 </td>
1720 <td>
1721 no
1722 </td>
1723 </tr>
1724 </tbody>
1725 </table>
1726 <p>
1727 The visibility of an element with ''backface-visibility: hidden'' is determined
1728 as follows:
1729 <ol>
1730 <li>
1731 For an element in a
1732 <span class="term">3D rendering context</span>,
1733 compute its
1734 <span class="term">
1735 accumulated 3D transformation matrix</span>. For an element
1736 not in a
1737 <span class="term">3D rendering context</span>,
1738 compute its
1739 <span class="term">transformation matrix</span>.
1740 </li>
1741 <li>
1742 If the component of the matrix in row 3, column 3 is
1743 negative, then the element should be hidden. Otherwise it
1744 is visible.
1745 </li>
1746 </ol>
1748 <p class="note">
1749 The reasoning for this definition is as follows. Assume
1750 elements are rectangles in the <var>x</var>–<var>y</var>
1751 plane with infinitesimal thickness. The front of the
1752 untransformed element has coordinates like (<var>x</var>,
1753 <var>y</var>, <var>ε</var>), and the back is
1754 (<var>x</var>, <var>y</var>, −<var>ε</var>), for
1755 some very small <var>ε</var>. We want to know if after
1756 the transformation, the front of the element is closer to the
1757 viewer than the back (higher <var>z</var>-value) or further
1758 away. The <var>z</var>-coordinate of the front will be
1759 <var>M</var><sub>13</sub><var>x</var> +
1760 <var>M</var><sub>23</sub><var>y</var> +
1761 <var>M</var><sub>33</sub><var>ε</var> +
1762 <var>M</var><sub>43</sub>, before accounting for perspective,
1763 and the back will be <var>M</var><sub>13</sub><var>x</var> +
1764 <var>M</var><sub>23</sub><var>y</var> −
1765 <var>M</var><sub>33</sub><var>ε</var> +
1766 <var>M</var><sub>43</sub>. The first quantity is greater than
1767 the second if and only if <var>M</var><sub>33</sub> > 0. (If
1768 it equals zero, the front and back are equally close to the
1769 viewer. This probably means something like a 90-degree
1770 rotation, which makes the element invisible anyway, so we don't
1771 really care whether it vanishes.)
1772 </p>
1774 <!-- ======================================================================================================= -->
1776 <h2 id="svg-transform">
1777 The SVG 'transform' Attribute
1778 </h2>
1780 <p>
1781 The <a href="http://www.w3.org/TR/2011/REC-SVG11-20110816/">SVG 1.1
1782 specification</a> did not specify the attributes 'transform', 'gradientTransform'
1783 or 'patternTransform' as <a
1784 href="http://www.w3.org/TR/2011/REC-SVG11-20110816/styling.html#UsingPresentationAttributes"><em>presentation
1785 attributes</em></a>. In order to improve the integration of SVG and HTML, this
1786 specification makes these SVG attributes 'presentation attributes' and makes the
1787 'transform' property one that applies to <span class="term">transformable
1788 elements</span> in the SVG namespace.
1789 </p>
1791 <p>
1792 This specification will also introduce the new presentation attributes
1793 'transform-origin', 'perspective', 'perspective-origin', 'transform-style' and
1794 'backface-visibility'.
1795 </p>
1797 <p>
1798 Values on new introduced presentation attributes get parsed following the syntax
1799 rules on <a href="#svg-data-types">SVG Data Types</a> [[SVG11]].
1800 </p>
1802 <h3 id="transform-attribute-specificity">
1803 SVG 'transform' attribute specificity
1804 </h3>
1806 <p>
1807 Since the previously named SVG attributes become presentation attributes, their
1808 participation in the CSS cascade is determined by the specificity of presentation
1809 attributes, as <a
1810 href="http://www.w3.org/TR/2011/REC-SVG11-20110816/styling.html#UsingPresentationAttributes">explained</a>
1811 in the SVG specification.
1812 </p>
1814 <div class="example">
1815 <p>
1816 This example shows the combination of the 'transform' style property and the
1817 'transform' presentation attribute.
1818 </p>
1820 <pre><svg xmlns="http://www.w3.org/2000/svg">
1821 <style>
1822 .container {
1823 transform: translate(100px, 100px);
1824 }
1825 </style>
1827 <g class="container" transform="translate(200 200)">
1828 <rect width="100" height="100" fill="blue" />
1829 </g>
1830 </svg></pre>
1832 <div class="figure">
1833 <img src="examples/svg-translate1.svg" width="470" height="240"
1834 alt="Translated SVG container element.">
1835 </div>
1837 <p>
1838 Because of the participation to the CSS cascade, the 'transform' style property
1839 overrides the 'transform' presentation attribute. Therefore the container gets
1840 translated by ''100px'' in both the horizontal and the vertical directions,
1841 instead of ''200px''.
1842 </p>
1843 </div>
1845 <h3 id="svg-syntax">
1846 Syntax of the SVG 'transform' attribute
1847 </h3>
1849 <p>
1850 To provide backwards compatibility, the syntax of the 'transform' presentation
1851 attribute differs from the syntax of the 'transform' style property as shown in the
1852 example above. However, the syntax used for the 'transform' style property can be
1853 used for a 'transform' presentation attribute value. Authors are advised to follow
1854 the rules of <a href="http://www.w3.org/TR/css3-values/#functional-notation">CSS
1855 Values and Units Module</a>. Therefore an author should write
1856 ''transform="translate(200px, 200px)"'' instead of
1857 ''transform="translate (200 200)"'' because the second example with the spaces
1858 before the ''('', the missing comma between the arguments and the values without the
1859 explicit unit notation would be valid for the attribute only.
1860 </p>
1862 <h4 id="svg-transform-list">
1863 Transform List
1864 </h4>
1866 <p>
1867 The value for the 'transform' attribute consists of a transform list with zero or
1868 more transform functions using <a href="#svg-functional-notation">functional
1869 notation</a>. If the transform list consists of more than one transform function,
1870 these functions are separated by optional whitespace, an optional comma ('','')
1871 and optional whitespace. The transform list can have optional whitespace characters
1872 before and after the list.
1873 </p>
1875 <h4 id="svg-functional-notation">
1876 Functional Notation
1877 </h4>
1879 <p>
1880 The syntax starts with the name of the function followed by optional whitespace
1881 characters followed by a left parenthesis followed by optional whitespace followed
1882 by the argument(s) to the notation followed by optional whitespace followed by a
1883 right parenthesis. If a function takes more than one argument, the arguments are
1884 either separated by a comma ('','') with optional whitespace characters before and
1885 after the comma, or by one or more whitespace characters.
1886 </p>
1888 <h4 id="svg-data-types">
1889 SVG Data Types
1890 </h4>
1892 <p>
1893 Arguments on all new introduced presentation attributes consist of data types in the
1894 sense of <a href="http://www.w3.org/TR/css3-values/#functional-notation">CSS Values
1895 and Units Module</a>. The definitions of data types in CSS Values and Units Module
1896 are enhanced as follows:
1897 </p>
1899 <h5 id="svg-transform-value">
1900 The <var><translation-value></var> and <var><length></var> type
1901 </h5>
1903 <p>
1904 A translation-value or length can be a <var><number></var> without an unit
1905 identifier. In this case the <a href="#svg-number"><var>number</var></a> gets
1906 interpreted as "user unit". A user unit in the the <a
1907 href="http://www.w3.org/TR/2003/REC-SVG11-20030114/coords.html#InitialCoordinateSystem">initial
1908 coordinate system</a> is equivalent to the parent environment's notion of a pixel
1909 unit.
1910 </p>
1912 <h5 id="svg-angle">
1913 The <var><angle></var> type
1914 </h5>
1916 <p>
1917 An angle can be a <var><number></var> without an unit identifier. In this case
1918 the <a href="#svg-number"><i>number</i></a> gets interpreted as a value in degrees.
1919 </p>
1921 <h5 id="svg-number">
1922 The <var><number></var> type
1923 </h5>
1925 <p>
1926 SVG supports scientific notations for numbers. Therefore a <var>number</var> gets
1927 parsed like described in SVG <a
1928 href="http://www.w3.org/TR/SVG/types.html#DataTypeNumber">Basic data types</a> for
1929 SVG attributes.
1930 </p>
1932 <h3 id="svg-gradient-transform-pattern-transform">
1933 The SVG 'gradientTransform' and 'patternTransform' attributes
1934 </h3>
1936 <p>
1937 SVG specifies the attributes 'gradientTransform' and 'patternTransform'. This
1938 specification makes both attributes presentation attributes. Both attributes use the
1939 same <a href="#svg-syntax">syntax</a> as the SVG 'transform' attribute. This
1940 specification does not introduce corresponding CSS style properties. Both, the
1941 'gradientTransform' and the 'patternTransform' attribute, are presentation
1942 attributes for the 'transform' property.
1943 </p>
1945 <h3 id="svg-transform-functions">
1946 SVG transform functions
1947 </h3>
1949 <p>
1950 For backwards compatibility with existing SVG content, this specification supports
1951 all transform functions defined by <a
1952 href="http://www.w3.org/TR/SVG/coords.html#TransformAttribute">The 'transform'
1953 attribute</a> in [[SVG11]]. Therefore the two-dimensional transform function
1954 ''rotate(<angle>)'' is extended as follows:
1955 </p>
1957 <dl>
1958 <dt id="rotate-three-function">
1959 <code class="css">rotate(<angle>[, <translation-value>,
1960 <translation-value>])</code>
1961 </dt>
1962 <dd>
1963 specifies a <a href="#RotateDefined">2D rotation</a> by the angle specified in the
1964 parameter about the origin of the element, as defined by the 'transform-origin'
1965 property. If the optional translation values are specified, the transform origin
1966 is translated by that amount (using the current transformation matrix) for the
1967 duration of the rotate operation. For example ''rotate(90deg, 100px, 100px)''
1968 would cause elements to appear rotated one-quarter of a turn in the clockwise
1969 direction after a translation of the transform-origin of 100 pixel in the
1970 horizontal and vertical directions.
1971 </dd>
1972 </dl>
1974 <p>
1975 User agents are just required to support the two optional arguments for translation
1976 on elements in the SVG namespace.
1977 </p>
1979 <h3 id="svg-three-dimensional-functions">SVG and 3D transform functions</h3>
1981 <p>
1982 This specification explicitly requires three-dimensional transform functions to
1983 apply to the <a
1984 href="http://www.w3.org/TR/SVG/intro.html#TermContainerElement"><em>container
1985 elements</em></a>: 'a', 'g', 'svg', all <a
1986 href="http://www.w3.org/TR/SVG/intro.html#TermGraphicsElement"><em>graphics
1987 elements</em></a>, all <a
1988 href="http://www.w3.org/TR/SVG/intro.html#TermGraphicsReferencingElement"><em>graphics
1989 referencing elements</em></a> and the SVG '<a
1990 href="http://www.w3.org/TR/SVG/extend.html#ForeignObjectElement">foreignObject</a>'
1991 element.
1992 </p>
1994 <p>
1995 Three-dimensional transform functions and the properties 'perspective',
1996 'perspective-origin', 'transform-style' and 'backface-visibility' can not be used
1997 for the elements: 'clipPath', 'linearGradient', 'radialGradient' and
1998 'pattern'. If a transform list includes a three-dimensional transform function, the
1999 complete transform list must be ignored. The values of every previously named
2000 property must be ignored. <span class="term">Transformable elements</span> that are
2001 contained by one of these elements can have three-dimensional transform functions.
2002 Before a 'clipPath', 'mask' or 'pattern' element can get applied to a target
2003 element, user agents must take the drawn results as static images in analogue of
2004 "flattening" the elements and taking the rendered content as a two-dimensional
2005 canvas.
2006 </p>
2008 <p>
2009 If the 'vector-effect' property is set to ''non-scaling-stroke'' and an object is
2010 within a <span class="term">3D rendering context</span>
2011 the property has no affect on stroking the object.
2012 </p>
2014 <h3 id="svg-user-coordinate-space">
2015 User coordinate space
2016 </h3>
2018 <p>
2019 For the 'pattern', 'linearGradient', 'radialGradient' and 'clipPath'
2020 elements the 'transform', 'patternTransform', 'gradientTransform' presentation
2021 attributes represents values in the current user coordinate system in place at the
2022 time when these elements are referenced (i.e., the user coordinate system for the
2023 element referencing the 'pattern' element via a 'fill' or 'stroke' property).
2024 Percentage values are relative to the <span>bounding box</span> of the
2025 referencing element.
2026 </p>
2028 <p>
2029 In particualar the 'patternUnit', 'gradientUnit' and 'maskUnit' attributes
2030 don't affect the user coordinate system used for transformations [[SVG11]].
2031 </p>
2033 <p>
2034 For all other <span class="term">transformable elements</span> the
2035 'transform' presentation attribute represents values in the current user coordinate
2036 system of the parent. All percentage values of the 'transform' presentation
2037 attribute are relative to the element's <var>bounding box</var>.
2038 </p>
2040 <div class="example">
2041 <p>
2042 The 'transform-origin' property on the pattern in the following example specifies
2043 a ''50%'' translation of the origin in the horizontal and vertical dimension. The
2044 'transform' property specifies a translation as well, but in absolute lengths.
2045 </p>
2047 <pre><svg xmlns="http://www.w3.org/2000/svg">
2048 <style>
2049 pattern {
2050 transform: rotate(45deg);
2051 transform-origin: 50% 50%;
2052 }
2053 </style>
2055 <defs>
2056 <pattern id="pattern-1">
2057 <rect id="rect1" width="100" height="100" fill="blue" />
2058 </pattern>
2059 </defs>
2061 <rect width="200" height="200" fill="url(#pattern-1)" />
2062 </svg></pre>
2064 <p>
2065 An SVG 'pattern' element doesn't have a bounding box. The <var>bounding box</var>
2066 of the referencing 'rect' element is used
2067 instead to solve the relative values of the 'transform-origin' property. Therefore
2068 the point of origin will get translated by 100 pixels temporarily to rotate the
2069 user space of the 'pattern' elements content.
2070 </p>
2071 </div>
2073 <h3 id="transform-attribute-dom">
2074 SVG DOM interface for the 'transform' attribute
2075 </h3>
2077 <p>
2078 The SVG specification defines the '<a
2079 href="http://www.w3.org/TR/2011/REC-SVG11-20110816/coords.html#InterfaceSVGAnimatedTransformList">SVGAnimatedTransformList</a>'
2080 interface in the SVG DOM to provide access to the animated and the base value of the
2081 SVG 'transform', 'gradientTransform' and 'patternTransform' attributes. To ensure
2082 backwards compatibility, this API must still be supported by user agents.
2083 </p>
2085 <p>
2086 The 'transform' property contributes to the CSS cascade. According to SVG 1.1 user
2087 agents conceptually insert a <a
2088 href="http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes">new author
2089 style sheet</a> for presentation attributes, which is the first in the author style
2090 sheet collection. 'baseVal' gives the author the possibility to access and modify
2091 the values of the SVG 'transform' attribute. To provide the necessary backwards
2092 compatibility to the SVG DOM, 'baseVal' must reflect the values of this author style
2093 sheet. All modifications to SVG DOM objects of 'baseVal' must affect this author
2094 style sheet immediately.
2095 </p>
2097 <p>
2098 'animVal' represents the computed style of the 'transform' property. Therefore it
2099 includes all applied <a
2100 href="http://www.w3.org/TR/css3-transitions/">CSS3 Transitions</a>, <a
2101 href="http://www.w3.org/TR/css3-animations/">CSS3 Animations</a> or <a
2102 href="#svg-animation">SVG Animations</a> if any of those are underway. The computed
2103 style and SVG DOM objects of 'animVal' can not be modified.
2104 </p>
2106 <p>
2107 The attribute '<a
2108 href="http://www.w3.org/TR/SVG/coords.html#__svg__SVGTransform__type">type</a>' of
2109 '<a
2110 href="http://www.w3.org/TR/SVG/coords.html#InterfaceSVGTransform">SVGTransform</a>'
2111 must return '<a
2112 href="http://www.w3.org/TR/SVG/coords.html#__svg__SVGTransform__SVG_TRANSFORM_UNKNOWN">SVG_TRANSFORM_UNKNOWN</a>'
2113 for <a href="#transform-functions">Transform Functions</a>
2114 or unit types that are not supported by this interface. If a two-dimensional
2115 transform function is not supported, the attribute '<a
2116 href="http://www.w3.org/TR/SVG/coords.html#__svg__SVGTransform__matrix">matrix</a>'
2117 must return a 3x2 '<a
2118 href="http://www.w3.org/TR/SVG/coords.html#InterfaceSVGMatrix">SVGMatrix</a>' with
2119 the corresponding values as described in the section <a
2120 href="#mathematical-description">Mathematical Description of Transform Functions</a>.
2121 </p>
2123 <h2 id="svg-animation">
2124 SVG Animation
2125 </h2>
2127 <h3 id="svg-animate-element">
2128 The 'animate' and 'set' element
2129 </h3>
2131 <p>
2132 With this specification, the 'animate' element and the 'set' element can animate
2133 the data type <var><transform-list></var>.
2134 </p>
2136 <p>
2137 The animation effect is post-multiplied to the underlying
2138 value for additive 'animate' animations (see below) instead of added to the
2139 underlying value, due to the specific behavior of <var><transform-list></var>
2140 animations.
2141 </p>
2143 <p>
2144 <var>From-to</var>, <var>from-by</var> and <var>by</var> animations are defined in
2145 SMIL to be equivalent to a corresponding <var>values</var> animation. However,
2146 <var>to</var> animations are a mixture of additive and non-additive behavior
2147 [[SMIL3]].
2148 </p>
2150 <p>
2151 <var>To</var> animations on 'animate' provide specific functionality to get a smooth
2152 change from the underlying value to the 'to' attribute value, which conflicts
2153 mathematically with the requirement for additive transform animations to be
2154 post-multiplied. As a consequence, the behavior of <var>to</var> animations for
2155 'animate' is undefined. Authors are suggested to use <var>from-to</var>,
2156 <var>from-by</var>, <var>by</var> or <var>values</var> animations to achieve any
2157 desired transform animation.
2158 </p>
2160 <p>
2161 The value 'paced' is undefined for the attribute 'calcMode' on 'animate' for animations of the
2162 data type <var><transform-list></var>. If specified,
2163 UAs may choose the value 'linear' instead. Future versions of this specification
2164 may define how paced animations can be performed on
2165 <var><transform-list></var>.
2166 </p>
2168 <p class="note">The following paragraphs extend <a
2169 href="http://www.w3.org/TR/SVG/animate.html#complexDistances">Elements, attributes
2170 and properties that can be animated</a> [[SVG11]].
2171 </p>
2173 <p>
2174 The introduce presentation attributes 'transform', 'transform-origin', 'perspective',
2175 'perspective-origin', 'transform-style' and 'backface-visibility' are animatable.
2176 'transform-style' and 'backface-visibility' are non-additive.
2177 </p>
2179 <p>
2180 With this specification the SVG basic data type <var><transform-list></var> is
2181 equivalent to a list of <var><transform-function></var>s.
2182 <var><transform-list></var> is animatable and additive. The data type can be
2183 animated using the SVG '<a
2184 href="http://www.w3.org/TR/SVG/animate.html#AnimateElement">animate</a>' element and
2185 the SVG '<a href="http://www.w3.org/TR/SVG/animate.html#SetElement">set</a>'
2186 element. SVG animations must run the same animation steps as described in section <a
2187 href="#animation">Transitions and Animations between Transform Values</a>.
2188 </p>
2190 <p>
2191 The set of animatable data types gets extended by <em><translation-value></em>.
2192 The new data type is animatable and additive.
2193 </p>
2195 <table class="data">
2196 <caption>Animatable data types</caption>
2197 <thead>
2198 <tr>
2199 <th>Data type</th>
2200 <th>Additive?</th>
2201 <th>'animate'</th>
2202 <th>'set'</th>
2203 <th>'animateColor'</th>
2204 <th>'animateTransform'</th>
2205 <th>Notes</th>
2206 </tr>
2207 </thead>
2208 <tbody>
2209 <tr>
2210 <th><var><transform-list></var></th>
2211 <td>yes</td>
2212 <td>yes</td>
2213 <td>yes</td>
2214 <td>no</td>
2215 <td>yes</td>
2216 <td>Additive for 'animateTransform' means that a transformation is post-multiplied to the base set of
2217 transformations.</td>
2218 </tr>
2219 <tr>
2220 <th><var><translation-value></var></th>
2221 <td>yes</td>
2222 <td>yes</td>
2223 <td>yes</td>
2224 <td>no</td>
2225 <td>no</td>
2226 <td> </td>
2227 </tr>
2228 </tbody>
2229 </table>
2231 <h3 id="neutral-element">
2232 Neutral element for addition
2233 </h3>
2235 <p>
2236 Some animations require a neutral element for addition. For transform functions
2237 this is a scalar or a list of scalars of 0. Examples of neutral elements for
2238 transform functions are ''translate(0)'', ''translate3d(0, 0, 0)'',
2239 ''translateX(0)'', ''translateY(0)'', ''translateZ(0)'', ''scale(0)'',
2240 ''scaleX(0)'', ''scaleY(0)'', ''scaleZ(0)'', ''rotate(0)'',
2241 ''rotate3d(v<sub>x</sub>, v<sub>y</sub>, v<sub>z</sub>, 0)'' (where <var>v</var> is
2242 a context dependent vector), ''rotateX(0)'', ''rotateY(0)'', ''rotateZ(0)'',
2243 ''skew(0, 0)'', ''skewX(0)'', ''skewY(0)'', ''matrix(0, 0, 0, 0, 0, 0)'', ''matrix3d(0, 0, 0, 0, 0,
2244 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)'' and ''perspective(0)''.
2245 </p>
2247 <p class="note">
2248 Animations to or from the neutral element of additions ''matrix'', ''matrix3d'' and
2249 ''perspective'' fall back to discrete animations (See <a
2250 href="#matrix-interpolation">Interpolation of Matrices</a>).
2251 </p>
2253 <div class="example">
2254 <p>
2255 A <var>by</var> animation with a by value v<sub>b</sub> is equivalent to the same
2256 animation with a values list with 2 values, the neutral element for addition for
2257 the domain of the target attribute (denoted 0) and v<sub>b</sub>, and
2258 ''additive="sum"''. [[SMIL3]]
2259 </p>
2261 <pre>
2262 <rect width="100" height="100">
2263 <animateTransform attributeName="transform" attributeType="XML"
2264 type="scale" by="1" dur="5s" fill="freeze"/>
2265 </rect></pre>
2267 <p>
2268 The neutral element for addition when performing a <var>by</var> animation with
2269 ''type="scale"'' is the value 0. Thus, performing the animation of the example
2270 above causes the rectangle to be invisible at time 0s (since the animated
2271 transform list value is ''scale(0)''), and be scaled back to its original size at
2272 time 5s (since the animated transform list value is ''scale(1)'').
2273 </p>
2275 </div>
2277 <h3 id="svg-attribute-name">
2278 The SVG 'attributeName' attribute
2279 </h3>
2281 <p>
2282 <a href="http://www.w3.org/TR/SVG/animate.html">SVG 1.1 Animation</a> defines the
2283 '<a href="http://www.w3.org/TR/SVG/animate.html#TargetAttributes">attributeName</a>'
2284 attribute to specify the name of the target attribute. For the presentation
2285 attributes 'gradientTransform' and 'patternTransform' it will also be possible to
2286 use the value 'transform'. The same 'transform' property will get animated.
2287 </p>
2289 <div class="example">
2290 <p>
2291 In this example the gradient transformation of the linear gradient gets animated.
2292 </p>
2294 <pre><linearGradient gradientTransform="scale(2)">
2295 <animate attributeName="gradientTransform" from="scale(2)" to="scale(4)"
2296 dur="3s" additive="sum"/>
2297 <animate attributeName="transform" from="translate(0, 0)" to="translate(100px, 100px)"
2298 dur="3s" additive="sum"/>
2299 </linearGradient></pre>
2301 <p>The 'linearGradient' element specifies the 'gradientTransform' presentation
2302 attribute. The two 'animate' elements address the target attribute
2303 'gradientTransform' and 'transform'. Even so all animations apply to the same
2304 gradient transformation by taking the value of the 'gradientTransform'
2305 presentation attribute, applying the scaling of the first animation and applying
2306 the translation of the second animation one after the other.
2307 </p>
2308 </div>
2310 <!-- ======================================================================================================= -->
2312 <h2 id="transform-functions">
2313 The Transform Functions
2314 </h2>
2315 <p>
2316 The value of the 'transform' property is a list of
2317 <var><transform-functions></var>. The set of allowed transform functions is
2318 given below. For <var><transform-functions></var> the type
2319 <var><translation-value></var> is defined as a <var><length></var> or
2320 <var><percentage></var> value, and the <var><angle></var> type is
2321 defined by <a
2322 href="http://www.w3.org/TR/css3-values/">CSS Values and Units Module.</a> Wherever
2323 <var><angle></var> is used in this specification, a <var><number></var>
2324 that is equal to zero is also allowed, which is treated the same as an angle of zero
2325 degrees.
2326 </p>
2328 <h3 id="two-d-transform-functions">2D Transform Functions</h3>
2329 <dl>
2330 <dt id="matrix-function">
2331 <code class="css">matrix(<number>, <number>, <number>, <number>, <number>, <number>)</code>
2332 </dt>
2333 <dd>
2334 specifies a 2D transformation in the form of a <a href="#MatrixDefined">transformation matrix</a> of the six values a-f.
2335 </dd>
2336 <dt id="translate-function">
2337 <code class="css">translate(<translation-value>[, <translation-value>])</code>
2338 </dt>
2339 <dd>
2340 specifies a <a href="#TranslateDefined">2D translation</a> by the vector [tx, ty], where tx is the first translation-value parameter and ty is the optional second translation-value parameter. If <em><ty></em> is not provided, ty has zero as a value.
2341 </dd>
2342 <dt id="translateX-function">
2343 <code class="css">translateX(<translation-value>)</code>
2344 </dt>
2345 <dd>
2346 specifies a <a href="#TranslateDefined">translation</a> by the given amount in the X direction.
2347 </dd>
2348 <dt id="translateY-function">
2349 <code class="css">translateY(<translation-value>)</code>
2350 </dt>
2351 <dd>
2352 specifies a <a href="#TranslateDefined">translation</a> by the given amount in the Y direction.
2353 </dd>
2354 <dt id="scale-function">
2355 <code class="css">scale(<number>[, <number>])</code>
2356 </dt>
2357 <dd>
2358 specifies a <a href="#ScaleDefined">2D scale</a> operation by the [sx,sy] scaling vector described by the 2 parameters. If the second parameter is not provided, it takes a value equal to the first. For example, scale(1, 1) would leave an element unchanged, while scale(2, 2) would cause it to appear twice as long in both the X
2359 and Y axes, or four times its typical geometric size.
2360 </dd>
2361 <dt id="scaleX-function">
2362 <code class="css">scaleX(<number>)</code>
2363 </dt>
2364 <dd>
2365 specifies a <a href="#ScaleDefined">2D scale</a> operation using the [sx,1] scaling vector, where sx is given as the parameter.
2366 </dd>
2367 <dt id="scaleY-function">
2368 <code class="css">scaleY(<number>)</code>
2369 </dt>
2370 <dd>
2371 specifies a <a href="#ScaleDefined">2D scale</a> operation using the [1,sy] scaling vector, where sy is given as the parameter.
2372 </dd>
2373 <dt id="rotate-function">
2374 <code class="css">rotate(<angle>)</code>
2375 </dt>
2376 <dd>
2377 specifies a <a href="#RotateDefined">2D rotation</a> by the angle specified in the parameter about the origin of the element, as
2378 defined by the 'transform-origin' property. For example, ''rotate(90deg)''
2379 would cause elements to appear rotated one-quarter of a turn in the clockwise direction.
2380 </dd>
2381 <dt>
2382 <code class="css">skew(<angle>[, <angle>])</code>
2383 </dt>
2384 <dd>
2385 specifies a <a href="#SkewDefined">2D skew</a> by [ax,ay] for X and Y. If the second parameter is not provided, it has a zero value.
2386 <p class="note">Note that the behavior of ''skew'' is different from mutliplying ''skewX'' with ''skewY''. Implementations must support this function for compatibility with legacy content.</p>
2387 </dd>
2388 <dt id="skewX-function">
2389 <code class="css">skewX(<angle>)</code>
2390 </dt>
2391 <dd>
2392 specifies a <a href="#SkewXDefined">2D skew transformation along the X axis</a> by the given angle.
2393 </dd>
2394 <dt id="skewY-function">
2395 <code class="css">skewY(<angle>)</code>
2396 </dt>
2397 <dd>
2398 specifies a <a href="#SkewYDefined">2D skew transformation along the Y axis</a> by the given angle.
2399 </dd>
2400 </dl>
2403 <h3 id="three-d-transform-functions">3D Transform Functions</h3>
2404 <dl>
2405 <dt id="matrix3d-function">
2406 <code class="css">matrix3d(<number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>)</code>
2407 </dt>
2408 <dd>
2409 specifies a 3D transformation as a 4x4 homogeneous matrix of 16 values in column-major order.
2410 </dd>
2411 <dt id="translate3d-function">
2412 <code class="css">translate3d(<translation-value>, <translation-value>, <length>)</code>
2413 </dt>
2414 <dd>
2415 specifies a <a href="#Translate3dDefined">3D translation</a> by the vector [tx,ty,tz], with tx, ty and tz being the first, second and third translation-value parameters respectively.
2416 </dd>
2417 <dt id="translateZ-function">
2418 <code class="css">translateZ(<length>)</code>
2419 </dt>
2420 <dd>
2421 specifies a <a href="#Translate3dDefined">3D translation</a> by the vector [0,0,tz] with the given amount in the Z direction.
2422 </dd>
2423 <dt id="scale3d-function">
2424 <code class="css">scale3d(<number>, <number>, <number>)</code>
2425 </dt>
2426 <dd>
2427 specifies a <a href="#Scale3dDefined">3D scale</a> operation by the [sx,sy,sz] scaling vector described by the 3 parameters.
2428 </dd>
2429 <dt id="scaleZ-function">
2430 <code class="css">scaleZ(<number>)</code>
2431 </dt>
2432 <dd>
2433 specifies a <a href="#Scale3dDefined">3D scale</a> operation using the [1,1,sz] scaling vector, where sz is given as the parameter.
2434 </dd>
2435 <dt id="rotate3d-function">
2436 <code class="css">rotate3d(<number>, <number>, <number>, <angle>)</code>
2437 </dt>
2438 <dd>
2439 specifies a <a href="#Rotate3dDefined">3D rotation</a> by the
2440 angle specified in last parameter about the [x,y,z] direction
2441 vector described by the first three parameters. A direction vector that cannot be normalized,
2442 such as [0,0,0], will cause the rotation to not be applied.
2443 <p class="note">Note that the rotation is clockwise as one looks from the end of
2444 the vector toward the origin.</p>
2445 </dd>
2446 <dt id="rotateX-function">
2447 <code class="css">rotateX(<angle>)</code>
2448 </dt>
2449 <dd>
2450 same as <code class="css">rotate3d(1, 0, 0, <angle>)</code>.
2451 </dd>
2452 <dt id="rotateY-function">
2453 <code class="css">rotateY(<angle>)</code>
2454 </dt>
2455 <dd>
2456 same as <code class="css">rotate3d(0, 1, 0, <angle>)</code>.
2457 </dd>
2458 <dt id="rotateZ-function">
2459 <code class="css">rotateZ(<angle>)</code>
2460 </dt>
2461 <dd>
2462 same as <code class="css">rotate3d(0, 0, 1, <angle>)</code>,
2463 which is also the same as <code class="css">rotate(<angle>)</code>.
2464 </dd>
2465 <dt id="perspective-function">
2466 <code class="css">perspective(<length>)</code>
2467 </dt>
2468 <dd>
2469 specifies a <a href="#PerspectiveDefined">perspective projection matrix</a>. This matrix scales points in
2470 X and Y based on their Z value, scaling points with positive Z values away from the origin, and those with
2471 negative Z values towards the origin. Points on the z=0 plane are unchanged. The parameter represents the
2472 distance of the z=0 plane from the viewer. Lower values give a more flattened pyramid and therefore a more
2473 pronounced perspective effect. For example, a value of 1000px gives a moderate amount of foreshortening
2474 and a value of 200px gives an extreme amount. The value for depth must be greater than zero, otherwise the
2475 function is invalid.
2476 </dd>
2477 </dl>
2479 <!-- ======================================================================================================= -->
2481 <h2 id="transform-function-lists">
2482 The Transform Function Lists
2483 </h2>
2485 <p>
2486 If a list of <var><transform-functions></var> is provided, then the net effect is as if each transform function had been specified separately in the order provided. For example,
2487 </p>
2489 <pre>
2490 <div style="transform:translate(-10px,-20px) scale(2) rotate(45deg) translate(5px,10px)"/>
2491 </pre>
2493 <p>
2494 is functionally equivalent to:
2495 </p>
2496 <pre>
2497 <div style="transform:translate(-10px,-20px)">
2498 <div style="transform:scale(2)">
2499 <div style="transform:rotate(45deg)">
2500 <div style="transform:translate(5px,10px)">
2501 </div>
2502 </div>
2503 </div>
2504 </div>
2505 </pre>
2506 <p>
2507 That is, in the absence of other styling that affects position and dimensions, a
2508 nested set of transforms is equivalent to a single list of transform functions,
2509 applied from the outside in. The resulting transform is the matrix multiplication of
2510 the list of transforms.
2511 </p>
2513 <p>
2514 If a transform function causes the <span class="term">current transformation matrix
2515 (CTM)</span> of an object to be non-invertible, the object and its content do not
2516 get displayed.
2517 </p>
2519 <div class="example">
2520 <p>
2521 The object in the following example gets scaled by 0.
2522 </p>
2524 <pre><style>
2525 .box {
2526 transform: scale(0);
2527 }
2528 </style>
2530 <div class="box">
2531 Not visible
2532 </div></pre>
2534 <p>
2535 The scaling causes a non-invertible CTM for the coordinate space of the div box.
2536 Therefore neither the div box, nor the text in it get displayed.
2537 </p>
2538 </div>
2540 <!-- ======================================================================================================= -->
2542 <h2 id="animation">
2543 Interpolation of Transforms
2544 </h2>
2546 <p>
2547 When animating or transitioning transforms, the transform function lists must be
2548 interpolated. For interpolation between one transform <em>from-transform</em> and
2549 a second transforms <em>to-transform</em>, the rules described below are applied.
2550 </p>
2552 <ul>
2553 <li id="none-none-animation">
2554 If both the <em>from-</em> and <em>to-transform</em> are ''none'':
2555 <ul>
2556 <li>
2557 There is no interpolation necessary. The computed value stays ''none''.
2558 </li>
2559 </ul>
2560 </li>
2561 <li id="none-transform-animation">
2562 If one of the <em>from-</em> or <em>to-transforms</em> is ''none''.
2563 <ul>
2564 <li>
2565 The value ''none'' is replaced by an equivalent
2566 <a href="#TermIdentityTransformFunction"><i>identity transform
2567 function</i></a> list for the corresponding transform
2568 function list. Both transform function lists get interpolated following the
2569 next rule.
2570 </li>
2571 </ul>
2572 <div class="example">
2573 <p>
2574 For example, if <em>from-transform</em> is ''scale(2)'' and
2575 <em>to-transform</em> is ''none'' then the value ''scale(1)'' will be used for
2576 <em>to-transform</em> and animation will proceed using the next rule.
2577 Similarly, if <em>from-transform</em> is ''none'' and <em>to-transform</em> is
2578 ''scale(2) rotate(50deg)'' then the animation will execute as if
2579 <em>from-transform</em> is ''scale(1) rotate(0)''.
2580 </p>
2581 </div>
2582 </li>
2583 <li id="transform-transform-animation">
2584 If <em>from-</em> and <em>to-transform</em> have the same number of
2585 transform functions, each transform function pair has either the same name, or is
2586 a derivative of the same <a href="#transform-primitives">primitive</a>.
2587 <ul>
2588 <li>
2589 Interpolate each transform function pair as described in <a
2590 href="#interpolation-of-transform-functions">Interpolation of transform
2591 functions</a>. The computed value is the resulting transform function
2592 list.
2593 </li>
2594 </ul>
2595 <div class="example">
2596 <p>
2597 For example, if <em>from-transform</em> is ''scale(1) translate(0)'' and
2598 <em>to-transform</em> is ''translate(100px) scale(2)'' then ''scale(1)'' and
2599 ''translate(100px)'' as well as ''translate(0)'' and ''scale(2)'' don't share
2600 a common primitive and therefore can not get interpolated following this rule.
2601 </p>
2602 </div>
2603 </li>
2604 <li id="other-animation">
2605 In all other cases:
2606 <ul>
2607 <li>
2608 The transform functions of each transform function list on the
2609 <em>from-</em> and <em>to-transform</em> get post multiplied and
2610 converted into 4x4 matrices. Each of the matrices gets interpolated following
2611 the instructions in <a href="#matrix-interpolation">Interpolation of
2612 matrices</a>. The computed value is the transform function ''matrix'' if both
2613 initial matrices can be represented by a correlating 3x2 matrix and
2614 ''matrix3d'' otherwise.
2615 </li>
2616 </ul>
2617 </li>
2618 </ul>
2620 <p>
2621 In some cases, an animation might cause a transformation matrix to be singular or
2622 non-invertible. For example, an animation in which scale moves from 1 to -1. At the
2623 time when the matrix is in such a state, the transformed element is not rendered.
2624 </p>
2626 <!-- ======================================================================================================= -->
2628 <h2 id="transform-primitives">
2629 Transform function primitives and derivatives
2630 </h2>
2632 <p>
2633 Some transform functions can be represented by more generic transform functions.
2634 These transform functions are called derived transform functions, the generic
2635 transform functions primitives. Primitives for two-dimensional and
2636 three-dimensional transform functions are listed below.
2637 </p>
2639 <p>
2640 Two-dimensional primitives with derived transform functions are:
2641 </p>
2643 <dl>
2644 <dt id="translate-primitive">
2645 <code class="css">translate(<translation-value>,
2646 <translation-value>)</code>
2647 </dt>
2648 <dd>
2649 for <code class="css">translateX(<translation-value>)</code>,
2650 <code class="css">translateY(<translation-value>)</code> and
2651 <code class="css">translate(<translation-value>)</code>.
2652 </dd>
2653 <dt id="rotate-three-primitive">
2654 <code class="css">rotate(<angle>, <translation-value>,
2655 <translation-value>)</code>
2656 </dt>
2657 <dd>
2658 for <code class="css">rotate(<angle>)</code> if
2659 <a href="#svg-transform-functions">rotate with three arguments</a> is supported.
2660 </dd>
2661 <dt id="scale-primitive">
2662 <code class="css">scale(<number>, <number>)</code>
2663 </dt>
2664 <dd>
2665 for <code class="css">scaleX(<number>)</code>, <code
2666 class="css">scaleY(<number>)</code> and <code
2667 class="css">scale(<number>)</code>.
2668 </dd>
2669 </dl>
2671 <p>
2672 Three-dimensional primitives with derived transform functions are:
2673 </p>
2675 <dl>
2676 <dt id="translate3d-primitive">
2677 <code class="css">translate3d(<translation-value>,
2678 <translation-value>, <length>)</code>
2679 </dt>
2680 <dd>
2681 for <code class="css">translateX(<translation-value>)</code>, <code
2682 class="css">translateY(<translation-value>)</code>, <code
2683 class="css">translateZ(<number>)</code> and <code
2684 class="css">translate(<translation-value>[,
2685 <translation-value>])</code>.
2686 </dd>
2687 <dt id="scale3d-primitive">
2688 <code class="css">scale3d(<number>, <number>, <number>)</code>
2689 </dt>
2690 <dd>
2691 for <code class="css">scaleX(<number>)</code>, <code
2692 class="css">scaleY(<number>)</code>, <code
2693 class="css">scaleZ(<number>)</code> and <code
2694 class="css">scale(<number>[, <number>])</code>.
2695 </dd>
2696 <dt id="rotate3d-primitive">
2697 <code class="css">rotate3d(<number>, <number>, <number>, <angle>)</code>
2698 </dt>
2699 <dd>
2700 for <code class="css">rotate(<number>)</code>, <code
2701 class="css">rotateX(<number>)</code>, <code
2702 class="css">rotateY(<number>)</code> and <code
2703 class="css">rotateZ(<number>)</code>.
2704 </dd>
2705 </dl>
2707 <p id="interpolation-two-three-dimensional-function">
2708 For derived transform functions that have a two-dimensional primitive and a
2709 three-dimensional primitive, the context decides about the used primitive. See
2710 <a href="#interpolation-of-transform-functions">Interpolation of primitives and
2711 derived transform functions</a>.
2712 </p>
2714 <!-- ======================================================================================================= -->
2716 <h2 id="interpolation-of-transform-functions">
2717 Interpolation of primitives and derived transform functions
2718 </h2>
2720 <p>
2721 Two transform functions with the same name and the same number of arguments are
2722 interpolated numerically without a former conversion. The calculated value will be
2723 of the same transform function type with the same number of arguments. Special rules
2724 apply to ''rotate3d'', ''matrix'', ''matrix3d'' and ''perspective''.
2725 </p>
2727 <div class="example">
2728 <p>
2729 The two transform functions ''translate(0)'' and ''translate(100px)'' are of the
2730 same type, have the same number of arguments and therefore can get interpolated
2731 numerically. ''translateX(100px)'' is not of the same type and
2732 ''translate(100px, 0)'' does not have the same number of arguments, therefore
2733 these transform functions can not get interpolated without a former conversion
2734 step.
2735 </p>
2736 </div>
2738 <p>
2739 Two different types of transform functions that share the same primitive, or
2740 transform functions of the same type with different number of arguments can be
2741 interpolated. Both transform functions need a former conversion to the common
2742 primitive first and get interpolated numerically afterwards. The computed value
2743 will be the primitive with the resulting interpolated arguments.
2744 </p>
2746 <div class="example">
2747 <p>
2748 The following example describes a transition from ''translateX(100px)'' to
2749 ''translateY(100px)'' in 3 seconds on hovering over the div box. Both transform
2750 functions derive from the same primitive <code
2751 class="css">translate(<translation-value>, <translation-value>)</code>
2752 and therefore can be interpolated.
2753 </p>
2755 <pre>div {
2756 transform: translateX(100px);
2757 }
2759 div:hover {
2760 transform: translateY(100px);
2761 transition: transform 3s;
2762 }</pre>
2764 <p>
2765 For the time of the transition both transform functions get transformed to the
2766 common primitive. ''translateX(100px)'' gets converted to ''translate(100px, 0)''
2767 and ''translateY(100px)'' gets converted to ''translate(0, 100px)''. Both
2768 transform functions can then get interpolated numerically.
2769 </p>
2770 </div>
2772 <p>
2773 If both transform functions share a primitive in the two-dimensional space, both
2774 transform functions get converted to the two-dimensional primitive. If one or both
2775 transform functions are three-dimensional transform functions, the common
2776 three-dimensional primitive is used.
2777 </p>
2779 <div class="example">
2780 <p>
2781 In this example a two-dimensional transform function gets animated to a
2782 three-dimensional transform function. The common primitive is <code
2783 class="css">translate3d</code>.
2784 </p>
2786 <pre>div {
2787 transform: translateX(100px);
2788 }
2790 div:hover {
2791 transform: translateZ(100px);
2792 transition: transform 3s;
2793 }</pre>
2795 <p>
2796 First '<code class="css">translateX(100px)</code>' gets converted to '<code
2797 class="css">translate3d(100px, 0, 0)</code>' and '<code class="css">translateZ(100px)</code>' to '<code
2798 class="css">translate3d(0, 0, 100px)</code>' respectively. Then both converted transform
2799 functions get interpolated numerically.
2800 </p>
2801 </div>
2803 <p>
2804 The transform functions ''matrix'', ''matrix3d'' and ''perspective''
2805 get converted into 4x4 matrices first and interpolated as defined in section <a
2806 href="#matrix-interpolation">Interpolation of Matrices</a> afterwards.
2807 </p>
2809 <p>
2810 For interpolatations with the primitive ''rotate3d'', the direction vectors of the
2811 transform functions get normalized first. If the
2812 normalized vectors are equal, the rotation angle gets interpolated numerically.
2813 Otherwise the transform functions get converted into 4x4 matrices first and
2814 interpolated as defined in section <a href="#matrix-interpolation">Interpolation of
2815 Matrices</a> afterwards.
2816 </p>
2818 <!-- ======================================================================================================= -->
2820 <h2 id="matrix-interpolation">
2821 Interpolation of Matrices
2822 </h2>
2824 <p>
2825 When interpolating between two matrices, each is decomposed into the corresponding
2826 translation, rotation, scale, skew and perspective values. Not all matrices can be
2827 accurately described by these values. Those that can't are decomposed into the most
2828 accurate representation possible, using the pseudocode in <a
2829 href="#matrix-decomposing">Decomposing the Matrix</a>. The resulting values get <a
2830 href="#matrix-values-interpolation">interpolated numerically</a> and <a
2831 href="#matrix-recomposing">recomposed back to a matrix</a> in a final step.
2832 </p>
2834 <div class="note">
2835 <p>
2836 In the following example the element gets translated by 100 pixel in both the X
2837 and Y directions and rotated by 1170 degree on hovering. The initial
2838 transformation is 45 degree. With the usage of transition, an author might expect
2839 a animated, clockwise rotation by three and a quarter turn (1170 degree).
2840 </p>
2842 <pre>
2843 <style>
2844 div {
2845 transform: rotate(45deg);
2846 }
2847 div:hover {
2848 transform: translate(100px, 100px) rotate(1215deg);
2849 transition: transform 3s;
2850 }
2851 </style>
2853 <div></div></pre>
2855 <p>
2856 The number of transform functions on the source transform
2857 ''rotate(45deg)'' differs from the number of transform functions on the
2858 destination transform ''translate(100px, 100px) rotate(1125deg)''.
2859 According to the last rule of <a href="#animation">Interpolation of
2860 Transforms</a>, both transforms must be interpolated by matrix interpolation.
2861 With converting the transformation functions to matrices, the information about
2862 the three turns gets lost and the element gets rotated by just a quarter turn (90
2863 degree).
2864 </p>
2866 <p>
2867 To achieve the three and a quarter turns for the example above, source and
2868 destination transforms must fulfill the third rule of <a
2869 href="#animation">Interpolation of Transforms</a>. Source transform could look
2870 like ''translate(0, 0) rotate(45deg)'' for a linearly interpolation of
2871 the transform functions.
2872 </p>
2873 </div>
2875 <p>
2876 If one of the matrices for interpolation is non-invertible, the used animation
2877 function must fallback to a discrete animation according to the rules of the
2878 respective animation specification.
2879 </p>
2881 <h3 id="matrix-decomposing">Decomposing the Matrix</h3>
2883 <p>
2884 The pseudocode below is based upon the "unmatrix" method in "Graphics Gems II,
2885 edited by Jim Arvo", but modified to use Quaternions instead of Euler angles to
2886 avoid the problem of Gimbal Locks.
2887 </p>
2889 <p>
2890 The following pseudocode works on a 4x4 homogeneous matrix:
2891 </p>
2893 <pre>
2894 Input: matrix ; a 4x4 matrix
2895 Output: translation ; a 3 component vector
2896 scale ; a 3 component vector
2897 skew ; skew factors XY,XZ,YZ represented as a 3 component vector
2898 perspective ; a 4 component vector
2899 quaternion ; a 4 component vector
2900 Returns false if the matrix cannot be decomposed, true if it can
2902 Supporting functions (point is a 3 component vector, matrix is a 4x4 matrix):
2903 double determinant(matrix) returns the 4x4 determinant of the matrix
2904 matrix inverse(matrix) returns the inverse of the passed matrix
2905 matrix transpose(matrix) returns the transpose of the passed matrix
2906 point multVecMatrix(point, matrix) multiplies the passed point by the passed matrix
2907 and returns the transformed point
2908 double length(point) returns the length of the passed vector
2909 point normalize(point) normalizes the length of the passed point to 1
2910 double dot(point, point) returns the dot product of the passed points
2911 double sqrt(double) returns the root square of passed value
2912 double max(double y, double x) returns the bigger value of the two passed values
2914 Decomposition also makes use of the following function:
2915 point combine(point a, point b, double ascl, double bscl)
2916 result[0] = (ascl * a[0]) + (bscl * b[0])
2917 result[1] = (ascl * a[1]) + (bscl * b[1])
2918 result[2] = (ascl * a[2]) + (bscl * b[2])
2919 return result
2921 // Normalize the matrix.
2922 if (matrix[3][3] == 0)
2923 return false
2925 for (i = 0; i < 4; i++)
2926 for (j = 0; j < 4; j++)
2927 matrix[i][j] /= matrix[3][3]
2929 // perspectiveMatrix is used to solve for perspective, but it also provides
2930 // an easy way to test for singularity of the upper 3x3 component.
2931 perspectiveMatrix = matrix
2933 for (i = 0; i < 3; i++)
2934 perspectiveMatrix[i][3] = 0
2936 perspectiveMatrix[3][3] = 1
2938 if (determinant(perspectiveMatrix) == 0)
2939 return false
2941 // First, isolate perspective.
2942 if (matrix[0][3] != 0 || matrix[1][3] != 0 || matrix[2][3] != 0)
2943 // rightHandSide is the right hand side of the equation.
2944 rightHandSide[0] = matrix[0][3];
2945 rightHandSide[1] = matrix[1][3];
2946 rightHandSide[2] = matrix[2][3];
2947 rightHandSide[3] = matrix[3][3];
2949 // Solve the equation by inverting perspectiveMatrix and multiplying
2950 // rightHandSide by the inverse.
2951 inversePerspectiveMatrix = inverse(perspectiveMatrix)
2952 transposedInversePerspectiveMatrix = transposeMatrix4(inversePerspectiveMatrix)
2953 perspective = multVecMatrix(rightHandSide, transposedInversePerspectiveMatrix)
2954 else
2955 // No perspective.
2956 perspective[0] = perspective[1] = perspective[2] = 0
2957 perspective[3] = 1
2959 // Next take care of translation
2960 for (i = 0; i < 3; i++)
2961 translate[i] = matrix[3][i]
2963 // Now get scale and shear. 'row' is a 3 element array of 3 component vectors
2964 for (i = 0; i < 3; i++)
2965 row[i][0] = matrix[i][0]
2966 row[i][1] = matrix[i][1]
2967 row[i][2] = matrix[i][2]
2969 // Compute X scale factor and normalize first row.
2970 scale[0] = length(row[0])
2971 row[0] = normalize(row[0])
2973 // Compute XY shear factor and make 2nd row orthogonal to 1st.
2974 skew[0] = dot(row[0], row[1])
2975 row[1] = combine(row[1], row[0], 1.0, -skew[0])
2977 // Now, compute Y scale and normalize 2nd row.
2978 scale[1] = length(row[1])
2979 row[1] = normalize(row[1])
2980 skew[0] /= scale[1];
2982 // Compute XZ and YZ shears, orthogonalize 3rd row
2983 skew[1] = dot(row[0], row[2])
2984 row[2] = combine(row[2], row[0], 1.0, -skew[1])
2985 skew[2] = dot(row[1], row[2])
2986 row[2] = combine(row[2], row[1], 1.0, -skew[2])
2988 // Next, get Z scale and normalize 3rd row.
2989 scale[2] = length(row[2])
2990 row[2] = normalize(row[2])
2991 skew[1] /= scale[2]
2992 skew[2] /= scale[2]
2994 // At this point, the matrix (in rows) is orthonormal.
2995 // Check for a coordinate system flip. If the determinant
2996 // is -1, then negate the matrix and the scaling factors.
2997 pdum3 = cross(row[1], row[2])
2998 if (dot(row[0], pdum3) < 0)
2999 for (i = 0; i < 3; i++)
3000 scale[i] *= -1;
3001 row[i][0] *= -1
3002 row[i][1] *= -1
3003 row[i][2] *= -1
3005 // Now, get the rotations out
3006 quaternion[0] = 0.5 * sqrt(max(1 + row[0][0] - row[1][1] - row[2][2], 0))
3007 quaternion[1] = 0.5 * sqrt(max(1 - row[0][0] + row[1][1] - row[2][2], 0))
3008 quaternion[2] = 0.5 * sqrt(max(1 - row[0][0] - row[1][1] + row[2][2], 0))
3009 quaternion[3] = 0.5 * sqrt(max(1 + row[0][0] + row[1][1] + row[2][2], 0))
3011 if (row[2][1] > row[1][2])
3012 quaternion[0] = -quaternion[0]
3013 if (row[0][2] > row[2][0])
3014 quaternion[1] = -quaternion[1]
3015 if (row[1][0] > row[0][1])
3016 quaternion[2] = -quaternion[2]
3018 return true</pre>
3020 <h3 id="matrix-values-interpolation">
3021 Interpolation of decomposed matrix values
3022 </h3>
3024 <p>
3025 Each component of the decomposed values translation, scale, skew and perspective of
3026 the source matrix get linearly interpolated with each corresponding component of the
3027 destination matrix.
3028 </p>
3030 <p class="note">
3031 For instance, <code>translate[0]</code> of the source matrix and
3032 <code>translate[0]</code> of the destination matrix are interpolated numerically,
3033 and the result is used to set the translation of the animating element.
3034 </p>
3036 <p>
3037 Quaternions of the decomposed source matrix are interpolated with quaternions of the
3038 decomposed destination matrix using the spherical linear interpolation (Slerp) as
3039 described by the pseudocode below:
3040 </p>
3042 <pre>
3043 Input: quaternionA ; a 4 component vector
3044 quaternionB ; a 4 component vector
3045 t ; interpolation parameter with 0 <= t <= 1
3046 Output: quaternionDst ; a 4 component vector
3048 Supporting functions (vector is a 4 component vector):
3049 double dot(vector, vector) returns the dot product of the passed vectors
3050 vector multVector(vector, vector) multiplies the passed vectors
3051 double sqrt(double) returns the root square of passed value
3052 double max(double y, double x) returns the bigger value of the two passed values
3053 double min(double y, double x) returns the smaller value of the two passed values
3054 double cos(double) returns the cosines of passed value
3055 double sin(double) returns the sine of passed value
3056 double acos(double) returns the inverse cosine of passed value
3059 product = dot(quaternionA, quaternionB)
3061 // Clamp product to -1.0 <= product <= 1.0
3062 product = max(product, 1.0)
3063 product = min(product, -1.0)
3065 if (product == 1.0)
3066 quaternionDst = quaternionA
3067 return
3069 theta = acos(dot)
3070 w = sin(t * theta) * 1 / sqrt(1 - product * product)
3072 for (i = 0; i < 4; i++)
3073 quaternionA[i] *= cos(t * theta) - product * w
3074 quaternionB[i] *= w
3075 quaternionDst[i] = quaternionA[i] + quaternionB[i]
3077 return</pre>
3079 <h3 id="matrix-recomposing">
3080 Recomposing the Matrix
3081 </h3>
3083 <p>
3084 After interpolation the resulting values are used to transform the elements user
3085 space. One way to use these values is to recompose them into a 4x4 matrix. This can
3086 be done following the pseudocode below:
3087 </p>
3089 <pre>
3090 Input: translation ; a 3 component vector
3091 scale ; a 3 component vector
3092 skew ; skew factors XY,XZ,YZ represented as a 3 component vector
3093 perspective ; a 4 component vector
3094 quaternion ; a 4 component vector
3095 Output: matrix ; a 4x4 matrix
3097 Supporting functions (matrix is a 4x4 matrix):
3098 matrix multiply(matrix a, matrix b) returns the 4x4 matrix product of a * b
3100 // apply perspective
3101 for (i = 0; i < 4; i++)
3102 matrix[i][3] = perspective[i]
3104 // apply translation
3105 for (i = 0; i < 3; i++)
3106 for (j = 0; j < 3; j++)
3107 matrix[3][i] += translation[j] * matrix[j][i]
3109 // apply rotation
3110 x = quaternion[0]
3111 y = quaternion[1]
3112 z = quaternion[2]
3113 w = quaternion[3]
3115 // Construct a composite rotation matrix from the quaternion values
3116 // rotationMatrix is a identity 4x4 matrix initially
3117 rotationMatrix[0][0] = 1 - 2 * (y * y + z * z)
3118 rotationMatrix[0][1] = 2 * (x * y - z * w)
3119 rotationMatrix[0][2] = 2 * (x * z + y * w)
3120 rotationMatrix[1][0] = 2 * (x * y + z * w)
3121 rotationMatrix[1][1] = 1 - 2 * (x * x + z * z)
3122 rotationMatrix[1][2] = 2 * (y * z - x * w)
3123 rotationMatrix[2][0] = 2 * (x * z - y * w)
3124 rotationMatrix[2][1] = 2 * (y * z + x * w)
3125 rotationMatrix[2][2] = 1 - 2 * (x * x + y * y)
3127 matrix = multiply(matrix, rotationMatrix)
3129 // apply skew
3130 // temp is a identity 4x4 matrix initially
3131 if (skew[2])
3132 temp[2][1] = skew[2]
3133 matrix = multiply(matrix, temp)
3135 if (skew[1])
3136 temp[2][1] = 0
3137 temp[2][0] = skew[1]
3138 matrix = multiply(matrix, temp)
3140 if (skew[0])
3141 temp[2][0] = 0
3142 temp[1][0] = skew[0]
3143 matrix = multiply(matrix, temp)
3145 // apply scale
3146 for (i = 0; i < 3; i++)
3147 for (j = 0; j < 3; j++)
3148 matrix[i][j] *= scale[i]
3150 return</pre>
3152 <h2 id="mathematical-description">
3153 Mathematical Description of Transform Functions
3154 </h2>
3156 <p>
3157 Mathematically, all transform functions can be represented as 4x4 transformation matrices of the following form:
3158 </p>
3159 <p>
3160 <img src="4x4matrix.png" alt="\begin{bmatrix} m11 & m21 & m31 & m41 \\ m12 & m22 & m32 & m42 \\ m13 & m23 & m33 & m43 \\ m14 & m24 & m34 & m44 \end{bmatrix}" width="222" height="106">
3161 <p>
3162 One translation unit on a matrix is equivalent to 1 pixel in the local coordinate system of the element.
3163 </p>
3165 <ul>
3166 <li id="MatrixDefined">
3167 <p>
3168 A 2D 3x2 matrix with six parameters <em>a</em>, <em>b</em>, <em>c</em>, <em>d</em>, <em>e</em> and <em>f</em> is equivalent to the matrix:
3169 </p>
3170 <img src="matrix.png" alt="\begin{bmatrix} a & c & 0 & e \\ b & d & 0 & f \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}" width="108" height="106">
3171 </li>
3172 <li id="TranslateDefined">
3173 <p>
3174 A 2D translation with the parameters <em>tx</em> and <em>ty</em> is equivalent to a <a href="#Translate3dDefined">3D translation</a> where <em>tz</em> has zero as a value.
3175 </p>
3176 </li>
3177 <li id="ScaleDefined">
3178 <p>
3179 A 2D scaling with the parameters <em>sx</em> and <em>sy</em> is equivalent to a <a href="#Scale3dDefined">3D scale</a> where <em>sz</em> has one as a value.
3180 </p>
3181 </li>
3182 <li id="RotateDefined">
3183 <p>
3184 A 2D rotation with the parameter <em>alpha</em> is
3185 equivalent to a <a href="#Rotate3dDefined">3D rotation</a>
3186 with vector [0,0,1] and parameter <em>alpha</em>.
3187 </p>
3188 </li>
3189 <li id="SkewDefined">
3190 <p>
3191 A 2D skew like transformation with the parameters <em>alpha</em> and <em>beta</em> is equivalent to the matrix:
3192 </p>
3193 <img src="skew.png" alt="\begin{bmatrix} 1 & \tan(\alpha) & 0 & 0 \\ \tan(\beta) & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}" width="205" height="106">
3194 </li>
3195 <li id="SkewXDefined">
3196 <p>
3197 A 2D skew transformation along the X axis with the parameter <em>alpha</em> is equivalent to the matrix:
3198 </p>
3199 <img src="skewX.png" alt="\begin{bmatrix} 1 & \tan(\alpha) & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}" width="155" height="106">
3200 </li>
3201 <li id="SkewYDefined">
3202 <p>
3203 A 2D skew transformation along the Y axis with the parameter <em>beta</em> is equivalent to the matrix:
3204 </p>
3205 <img src="skewY.png" alt="\begin{bmatrix} 1 & 0 & 0 & 0 \\ \tan(\beta) & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}" width="155" height="106">
3206 </li>
3207 <li id="Translate3dDefined">
3208 <p>
3209 A 3D translation with the parameters <em>tx</em>, <em>ty</em> and <em>tz</em> is equivalent to the matrix:
3210 </p>
3211 <img src="translate3d.png" alt="\begin{bmatrix} 1 & 0 & 0 & tx \\ 0 & 1 & 0 & ty \\ 0 & 0 & 1 & tz \\ 0 & 0 & 0 & 1 \end{bmatrix}" width="114" height="106">
3212 </li>
3213 <li id="Scale3dDefined">
3214 <p>
3215 A 3D scaling with the parameters <em>sx</em>, <em>sy</em> and <em>sz</em> is equivalent to the matrix:
3216 </p>
3217 <img src="scale3d.png" alt="\begin{bmatrix} sx & 0 & 0 & 0 \\ 0 & sy & 0 & 0 \\ 0 & 0 & sz & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}" width="137" height="106">
3218 </li>
3219 <li id="Rotate3dDefined">
3220 <p>
3221 A 3D rotation with the vector [x,y,z] and the parameter <em>alpha</em> is equivalent to the matrix:
3222 </p>
3223 <img src="rotate3dmatrix.png" alt="\begin{bmatrix} 1 - 2 \cdot (y^2 + z^2) \cdot sq & 2 \cdot (x \cdot y \cdot sq - z \cdot sc) & 2 \cdot (x \cdot z \cdot sq + y \cdot sc) & 0 \\ 2 \cdot (x \cdot y \cdot sq + z \cdot sc) & 1 - 2 \cdot (x^2 + z^2) \cdot sq & 2 \cdot (y \cdot z \cdot sq - x \cdot sc) & 0 \\ 2 \cdot (x \cdot z \cdot sq - y \cdot sc) & 2 \cdot (y \cdot z \cdot sq + x \cdot sc) & 1 - 2 \cdot (x^2 + y^2) \cdot sq & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}" width="647" height="106">
3224 <p>
3225 where:
3226 </p>
3227 <img src="rotate3dvariables.png" alt="\newline sc = \sin (\alpha/2) \cdot \cos (\alpha/2) \newline sq = \sin^2 (\alpha/2)" width="221" height="50">
3228 </li>
3229 <li id="PerspectiveDefined">
3230 <p>
3231 A perspective projection matrix with the parameter <em>d</em> is equivalent to the matrix:
3232 </p>
3233 <img src="perspective.png" alt="\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & -1/d & 1 \end{bmatrix}" width="143" height="106">
3234 </li>
3235 </ul>
3237 <h2>Conformance</h2>
3238 <!--conformance-->
3240 <h2>References</h2>
3242 <h3 class="no-num">Normative references</h3>
3243 <!--normative-->
3245 <h3 class="no-num">Other references</h3>
3246 <!--informative-->
3250 <h2 class="no-num">Property index</h2>
3251 <!-- properties -->
3255 <h2 class="no-num" id="index">Index</h2>
3256 <!--index-->
3258 </body>
3259 </html>
3260 <!-- Keep this comment at the end of the file
3261 Local variables:
3262 mode: sgml
3263 sgml-declaration:"~/SGML/HTML4.decl"
3264 sgml-default-doctype-name:"html"
3265 sgml-minimize-attributes:t
3266 sgml-nofill-elements:("pre" "style" "br")
3267 sgml-live-element-indicator:t
3268 sgml-omittag:nil
3269 sgml-shorttag:nil
3270 sgml-namecase-general:t
3271 sgml-general-insert-case:lower
3272 sgml-always-quote-attributes:t
3273 sgml-indent-step:nil
3274 sgml-indent-data:t
3275 sgml-parent-document:nil
3276 sgml-exposed-tags:nil
3277 sgml-local-catalogs:nil
3278 sgml-local-ecat-files:nil
3279 End:
3280 -->