# Coordinate Conversion Made Easy – the power of GeometryUtils

In a previous post we introduced the GeometryUtils interface and the `getBoxQuads()` API for retrieving the CSS box geometry of a DOM node. GeometryUtils also takes care of another important problem: converting coordinates reliably from one DOM node to another. For example, you might want to find the bounding-box of one element relative to another element, or you might want to convert event coordinates from the viewport to some arbitrary element.

## Existing APIs

Until now, simple cases could be handled using `getBoundingClientRect()` and some math, but complex cases (e.g. involving CSS transforms) were almost impossible to handle using standard APIs. The nonstandard APIs `webkitConvertPointToPage` and `webkitConvertPageToPoint` are a big improvement, but apart from not being standardized, they’re not as powerful as they need to be. In particular it’s more convenient and more robust to provide an API for directly converting coordinates from one element to another.

## New APIs

`GeometryUtils` introduces three new methods for coordinate conversion:

• `to.convertPointFromNode(point, from)` converts a a point relative to the top-left of the first border-box of “from” to a point relative to the top-left of the first border-box of “to”. The point is a `DOMPointInit`, which means you can pass a `DOMPoint` or a JS object such as `{x:0, y:0}`.
• `to.convertRectFromNode(rect, from)` converts a a `DOMRect` relative to the top-left of the first border-box of “from” to a DOMQuad relative to the top-left of the first border-box of “to” by converting the vertices of the `DOMRect`. It converts to a `DOMQuad` to ensure that the result is accurate even if it needs to be rotated or skewed by CSS transforms.
• `to.convertQuadFromNode(quad, from)` converts a `DOMQuad` from “from” to “to”. It’s just like `convertRectFromNode` except for taking a `DOMQuad`.

As with `getBoxQuads`, a node can be an `Element`, `TextNode` or `Document`; when a `Document` is used, the coordinates are relative to the document’s viewport.

Example:

``` <div id="d" style="position:absolute; transform:rotate(45deg); left:100px; top:100px; width:100px; height:100px;"></div> <div id="e" style="position:absolute; left:100px; top:100px; width:100px; height:100px;"></div> ```
``` var p1 = document.convertPointFromNode({ x:0, y:0 }, document.getElementById("e") ); // p1.x == 100, p1.y == 100   var p2 = document.convertPointFromNode({ x:0, y:0 }, document.getElementById("d") ); // p2.x == 150, p2.y == 150 - 50*sqrt(2) (approx)   p2 = document.getElementById("e").convertPointFromNode({ x:0, y:0 }, document.getElementById("d") ); // p2.x == 50, p2.y == 50 - 50*sqrt(2) (approx)   var q1 = document.convertRectFromNode( new DOMRect(0, 0, 50, 50), document.getElementById("e") ); // q1.p1.x == 100, q1.p1.y == 100 // q1.p2.x == 150, q1.p2.y == 100 // q1.p3.x == 150, q1.p3.y == 150 // q1.p4.x == 100, q1.p4.y == 150   var q2 = document.convertQuadFromNode( new DOMQuad({ x:60, y:50 }, { x:90, y:50 }, { x:100, y:100 }, { x:50, y:100 }), document.getElementById("e") ); // q2.p1.x == 100, q2.p1.y == 100 // q2.p2.x == 150, q2.p2.y == 100 // q2.p3.x == 140, q2.p3.y == 150 // q2.p4.x == 110, q2.p4.y == 150 ```
p1
p2 Sometimes it’s useful to convert to or from an element’s CSS content-box, padding-box or margin-box. This is supported via an optional `ConvertCoordinateOptions` dictionary with the following options:

• `fromBox`: one of `"content"`, `"padding"`, `"border"` or `"margin"`, selecting which CSS box of the first fragment of the `from` node the input point(s) are relative to.
• `toBox`: selects which CSS box of the first fragment of the `to` node the returned point(s) are relative to.

As a special case, this makes it easy to convert points between different
CSS box types of the same element. For example, to convert a point from an
element’s border-box to be relative to its content-box, use
`element.convertPointFromNode(point, element, {toBox:"content"})`.

Example:

``` <div id="e" style="position:absolute; padding:20px; left:100px; top:100px; width:60px; height:60px;"></div> ```
``` var p1 = document.convertPointFromNode({ x:0, y:0 }, document.getElementById("e"), {fromBox:"content"} ); // p1.x == 120, p1.y == 120   p1 = document.getElementById("e").convertPointFromNode({ x:120, y:120 }, document, {toBox:"content"} ); // p1.x == 0, p1.y == 0   p1 = document.getElementById("e").convertPointFromNode({ x:0, y:0 }, document.getElementById("e"), {fromBox:"content"} ); // p1.x == 20, p1.y == 20   p1 = document.getElementById("e").convertPointFromNode({ x:20, y:20 }, document.getElementById("e"), {toBox:"content"} ); // p1.x == 0, p1.y == 0 ```
p1
e content-box
e border-box

These APIs are available in Firefox nightly builds and should be released in Firefox 31. Firefox is the first browser to implement these APIs.

#### Footnote

 Consider the following example:

``` <div style="transform:scale(0)"> <div id="a">...<> <div id="b">...<> </div> ```

In this case, converting a point relative to `a` to be relative to `b` by converting first to page coordinates and then back to `b` doesn’t work, because the `scale(0)` maps every point in `a` to a single point in the page.

View full post on Mozilla Hacks – the Web developer blog