How to Translate from DOM to SVG Coordinates and Back Again

Share this article

How to Translate from DOM to SVG Coordinates and Back Again

Using SVGs is relatively straight forward — until you want to mix DOM and vector interactions.

SVGs have their own coordinate system defined in a viewBox attribute. For example:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">

This sets a width of 800 units and a height of 600 units starting at 0,0. These units are arbitrary measurements for drawing purposes, and it’s possible to use fractions of a unit. If you position this SVG in an 800 by 600 pixel area, each SVG unit should map directly to a screen pixel.

However, vector images can be scaled to any size — especially in a responsive design. Your SVG could be scaled down to 400 by 300 or even stretched beyond recognition in a 10 by 1000 space. Adding further elements to this SVG becomes more difficult if you want to place them according to the cursor location.

Note: see Sara Soueidan’s viewport, viewBox and preserveAspectRatio article for more information about SVG coordinates.

Avoid Coordinate Translation

You may be able to avoid translating between coordinate systems entirely.

SVGs embedded in the HTML page (rather than an image or CSS background) become part of the DOM and can be manipulated in a similar way to other elements. For example, take a basic SVG with a single circle:

<svg id="mysvg" xmlns="https://www.w3.org/2000/svg" viewBox="0 0 800 600" preserveAspectRatio="xMidYMid meet">
  <circle id="mycircle" cx="400" cy="300" r="50" />
<svg>

You can apply CSS effects to this:

circle {
  stroke-width: 5;
  stroke: #f00;
  fill: #ff0;
}

circle:hover {
  stroke: #090;
  fill: #fff;
}

You can also attach event handlers to modify attributes:

const mycircle = document.getElementById('mycircle');

mycircle.addEventListener('click', (e) => {
  console.log('circle clicked - enlarging');
  mycircle.setAttribute('r', 60);
});

The following example adds thirty random circles to an SVG image, applies a hover effect in CSS, and uses JavaScript to increase the radius by ten units when a circle is clicked.

See the Pen SVG interaction by SitePoint (@SitePoint) on CodePen.

SVG to DOM Coordinate Translation

It may become necessary to overlay a DOM element on top of an SVG element — for example, a menu or information box on the active country shown on a world map. Presuming the SVG is embedded into the HTML, elements become part of the DOM, so the getBoundingClientRect() method can be used to extract the position and dimensions. (Open the console in the example above to reveal the clicked circle’s new attributes following a radius increase.)

Element.getBoundingClientRect() is supported in all browsers and returns an DOMrect object with the following properties in pixel dimensions:

  • .x and .left: x-coordinate, relative to the viewport origin, of the left side of the element
  • .right: x-coordinate, relative to the viewport origin, of the right side of the element
  • .y and .top: y-coordinate, relative to the viewport origin, of the top side of the element
  • .bottom: y-coordinate, relative to the viewport origin, of the bottom side of the element
  • .width: width of the element (not supported in IE8 and below but is identical to .right minus .left)
  • .height: height of the element (not supported in IE8 and below but is identical to .bottom minus .top)

All coordinates are relative to the browser viewport and will therefore change as the page is scrolled. The absolute location on the page can be calculated by adding window.scrollX to .left and window.scrollY to .top.

DOM to SVG Coordinate Translation

This is more challenging. Presume you want to position a new SVG element on its viewBox at the position where a click event occurs. The event handler object provides the DOM .clientX and .clientY pixel coordinates, but these must be translated to SVG units.

It’s tempting to think you can calculate the coordinates of an SVG point by applying multiplication factors. For example, if a 1000-unit–width SVG is placed in a 500px width container, you can multiply any the DOM x coordinate by two to get the SVG location. It won’t work! …

  • There is no guarantee the SVG fits exactly into your container.
  • If the element dimensions change — perhaps in response to the user resizing the browser — the width and height factors must be re-calculated.
  • The SVG or one or more elements could be transformed in 2D or 3D space.
  • Even if you overcome these hurdles, it never quite works as you expect, and there’s often a margin of error.

Fortunately, SVGs provide their own matrix factoring mechanisms to translate coordinates. The first step is to create a point on the SVG using the createSVGPoint() method and pass in the screen/event x and y coordinates:

const
  svg = document.getElementById('mysvg'),
  pt = svg.createSVGPoint();

pt.x = 100;
pt.y = 200;

You can then apply a matrix transformation created from an inverse of the SVG’s .getScreenCTM() method, which maps SVG units to screen coordinates:

const svgP = pt.matrixTransform( svg.getScreenCTM().inverse() );

svgP now has .x and .y properties, which provide the coordinate on the SVG viewBox.

The following code places a circle at a point clicked on an SVG canvas:

// get SVG element and namespace
const
  svg = document.getElementById('mysvg'),
  NS = svg.getAttribute('xmlns');

// click event
svg.addEventListener('click', (e) => {

  const pt = svg.createSVGPoint();

  // pass event coordinates
  pt.x = e.clientX;
  pt.y = e.clientY;

  // transform to SVG coordinates
  const svgP = pt.matrixTransform( svg.getScreenCTM().inverse() );

  // add new SVG element
  const circle = document.createElementNS(NS, 'circle');
  circle.setAttribute('cx', svgP.x);
  circle.setAttribute('cy', svgP.y);
  circle.setAttribute('r', 10);

  svg.appendChild(circle);

});

Note: the createElementNS() methods is identical to the standard DOM createElement() method, except that it specifies an XML namespace URI. In other words, it acts on an SVG document rather than the HTML.

Translating to Transformed SVG Coordinates

There’s a further complication. The SVG or individual elements can be transformed by translating, scaling, rotating, and/or skewing, which affects the resulting SVG coordinate. For example, the following <g> layer is 4x larger than the standard SVG units, so coordinates will be one quarter those of the containing SVG:

<g id="transformed" transform="scale(4)">
  <rect x="50" y="50" width="100" height="100" />
</g>

The resulting rectangle appears to have a 400 unit width and height at position 200, 200.

Fortunately, the .getScreenCTM() method can be applied to any element as well as the SVG itself. The resulting matrix considers all transformations so you can create a simple svgPoint() translation function:

const
  svg = document.getElementById('mysvg'),
  transformed = svg.getElementById('transformed');

console.log( svgPoint(svg, 10, 10) ); // returns x, y
console.log( svgPoint(transformed, 10, 10) ); // = x/4, y/4

// translate page to SVG coordinate
function svgPoint(element, x, y) {

  const pt = svg.createSVGPoint();
  pt.x = x;
  pt.y = y;

  return pt.matrixTransform( element.getScreenCTM().inverse() );

}

The following demonstration works in all modern browsers, (and would work in IE11 if you convert the JavaScript to ES5!). A circle is added at the cursor point when the SVG is tapped/clicked.

This also occurs when a transformed <g> area is clicked, but that element rather than the SVG itself is passed to the svgPoint() function to ensure the correct coordinate is calculated:

See the Pen DOM to SVG co-ordinate translation by Craig Buckler (@craigbuckler) on CodePen.

Ideally, it’s best to avoid DOM to/from SVG coordinate translation but, when that’s not possible, use the methods described above to ensure the process is robust at all page dimensions.

Frequently Asked Questions on Translating from DOM to SVG Coordinates and Back Again

What is the Difference Between DOM and SVG Coordinates?

The Document Object Model (DOM) and Scalable Vector Graphics (SVG) are both integral parts of web development, but they serve different purposes. DOM is a programming interface for HTML and XML documents. It represents the structure of a document and allows a way to manipulate its content and visual presentation. On the other hand, SVG is an XML-based vector image format for two-dimensional graphics. The main difference between the two lies in their coordinate systems. DOM uses a pixel-based coordinate system, while SVG uses a system based on the viewBox attribute, which can be scaled and transformed.

How Do I Convert DOM Coordinates to SVG?

Converting DOM coordinates to SVG involves using the SVG element’s createSVGPoint method to create a point in the SVG coordinate system. Then, you can use the matrixTransform method to convert the point to the SVG coordinate system. This method takes a DOMMatrix object, which represents the transformation matrix of the SVG element.

How Do I Convert SVG Coordinates Back to DOM?

To convert SVG coordinates back to DOM, you can use the inverse method of the SVGMatrix object. This method returns a new SVGMatrix object that is the inverse of the original matrix. By multiplying the SVG point by this inverse matrix, you can convert it back to the DOM coordinate system.

What is the Role of the viewBox Attribute in SVG?

The viewBox attribute in SVG is used to specify the aspect ratio and coordinate system of the SVG image. It allows you to control the scaling and positioning of the SVG elements. The viewBox attribute takes four values: min-x, min-y, width, and height. These values define a rectangle in the SVG coordinate system.

How Can I Use the DOM-to-SVG Package in My Project?

The DOM-to-SVG package is a useful tool for converting DOM coordinates to SVG and vice versa. To use it in your project, you need to install it using npm, a package manager for the JavaScript programming language. Once installed, you can require it in your JavaScript file and use its methods to perform the conversion.

What is the cx Attribute in SVG?

The cx attribute in SVG is used to specify the x-coordinate of the center of a circle. It is one of the basic attributes for creating circles in SVG. The value of the cx attribute is a length in the user coordinate system.

Can I Use DOM and SVG Together in a Web Page?

Yes, you can use DOM and SVG together in a web page. SVG is embedded in HTML, and therefore, it is part of the DOM. You can manipulate SVG elements using DOM methods and properties. This allows you to create dynamic and interactive graphics on your web page.

How Does the Coordinate System in SVG Differ from That in HTML?

The coordinate system in SVG is different from that in HTML. In HTML, the coordinate system is pixel-based, with the origin at the top-left corner of the page. In SVG, the coordinate system is defined by the viewBox attribute, with the origin at the top-left corner of the viewBox. This allows SVG graphics to be scalable and resolution-independent.

How Can I Transform SVG Coordinates?

You can transform SVG coordinates using the transform attribute. This attribute allows you to apply various transformations, such as translation, rotation, scaling, and skewing, to an SVG element. The value of the transform attribute is a list of transformation functions, each of which is applied to the element in the order they are listed.

What are Some Common Use Cases for Converting Between DOM and SVG Coordinates?

Converting between DOM and SVG coordinates is useful in many scenarios. For example, if you are creating an interactive SVG graphic, you might need to convert mouse coordinates (which are in the DOM coordinate system) to SVG coordinates to manipulate SVG elements. Conversely, if you are creating a custom SVG element, you might need to convert its coordinates back to the DOM coordinate system to position it correctly on the page.

Craig BucklerCraig Buckler
View Author

Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.

DOM interactionDOM manipulationpatrickcSVG
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week