How to Translate from DOM to SVG Coordinates and Back Again?

JavascriptProgramming ScriptsWeb DevelopmentFront End Technology

In this tutorial, we will learn about the procedure to translate from DOM to SVG and vice versa.

SVG- The full name of SVG is Scalable Vector Graphics, which is an image type made using XML code and can be edited or created in any text editor. Its two-dimensional vector-based graphic image is used for websites. The vector image has the specification that it can be scaled to any size, and it will not affect its quality.

SVG is a DOM-based image, it does not depend upon resolution so this can be changed using CSS and we can also attach a JavaScript handler to it. It is mostly used for high-performance, dynamic, flexible applications.

We define svg coordinate system using ViewBox −

<svg xmlns= "http://www.w3.org/2000/svg" viewBox="10 8 900 600">

10 8 are starting coordinate and 900, 600 are width and height respectively.

Example

Let’s draw a circle using SVG −

<html> <head> <title>Translate DOM to SVG and Back again.</title> </head> <body> <svg viewBox="10 10 900 600" preserveAspectRatio="xMidYMid meet"> <circle id="mysvg" cx="450" cy="250" r="60" stroke-width="8" fill="green"/> <svg> </body> </html>

Let’s add CSS and event listener JavaScript effect on this SVG

CSS

#mysvg:hover{ fill: yellow; stroke: red; cursor: pointer; }

JavaScript

<script> let svgEx=document.getElementById("svgEx"); svgEx.addEventListener('click', (event)=>{ alert("Clicked"); }) </script>

Example

<html> <head> <title>Translate DOM to SVG and Back again.</title> <style> #svgEx:hover{ fill: yellow; stroke: red; cursor: pointer; } </style> </head> <body> <svg viewBox="10 10 900 600" preserveAspectRatio="xMidYMid meet"> <circle id="svgEx" cx="450" cy="250" r="60" stroke-width="8" fill="green"/> <svg> <script> let svgEx=document.getElementById("svgEx"); svgEx.addEventListener('click', (event)=>{ alert("Clicked"); }) </script> </body> </html>

Translation SVG to DOM

We sometimes need to add DOM elements over the SVG item, so in that case, we can use getBoundingClientRect() method which returns the DOM object and it’s eight position properties in pixel dimensions. So, when SVG is imbedded into HTML then it also becomes part of the DOM.

The getBoundingClientRect() returns the position as size of the item.

With properties- x,y, Width, Height, Left, Right, Top, Bottom.

Syntax

element.getBoundingClientRect()

Translation DOM to SVG

It’s very helpful and difficult to translate from DOM to SVG. Take a scenario where we want to get the position of an item where a click event occurs so we can get the position using DOM property pixel coordinates .clientX and .clientY. so, we translate it to SVG.

Here are some challenges that can occur when we convert to SVG.

  • It might not work as expected.
  • Not sure that SVG will fit into the container.
  • The browser will have to re-calculate height and width in case element dimension changes.

SVG has a mechanism of matrix factoring to translate coordinates using createCVGpoint(); and we pass the coordinate value of event x,y where the event listener click happened. Then we apply a matrix transformation using .matrixTransform method. By, doing inverse of SVG using .getScreenCTM() method matrix is created which maps SVG unit to screen coordinates.

let ele=document.getElementById(“svgEx”); let point= ele.createSVGPoint(); point.x=100; point.y=200; var pointSvgLoc= point.matrixTransform(svg.getScreenCTM().inverse());

So, eventually, we will have the location of the SVG coordinate and by using .x and .y properties we can place the element at the point clicked.

Let’s have a function for getting coordinate and this function will ensure that correct coordinates position calculated.

// translate page to SVG co-ordinate function Get_SVG_Coordinate(svg, x, y) { var pt = svg.createSVGPoint(); pt.x = x; pt.y = y; return pt.matrixTransform(svg.getScreenCTM().inverse()); }

Event listener function to create circle on point where click event happened.

function Click_Circle_create(event){ //if circle clicked then don't create new circle if (event.target.nodeName === 'circle') return; const svgPoint =Get_SVG_Coordinate(svg, event.clientX, event.clientY), cX=Math.round(svgPoint.x), cY=Math.round(svgPoint.y); // add new SVG element const circle = document.createElementNS(NS, 'circle'); circle.setAttribute('cx', cX); circle.setAttribute('cy', cY); circle.setAttribute('r', 20); svg.appendChild(circle); }

Here createElementNS() works as an SVG document and it is same as DOM createElement() standard DOM method, it specifies and XML namespace URI which provide a simple method for qualifying element and attribute names used in Extensible markup language by associating them with namespaces.

Example

Complete Program

<html> <head> <title>Translate DOM to SVG and Back again.</title> <style> html { height: 100%; } #mysvg circle { stroke-width: 3; stroke: #F51720; fill: blue; } #mysvg circle:hover{ stroke: #116530; fill: #050A30; } </style> </head> <body> <p> Click anywhere on the output window </p> <svg xmlns="http://www.w3.org/2000/svg" id="mysvg" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMid meet"> <script> const svg = document.getElementById('mysvg'), NS = svg.getAttribute('xmlns'); // click event svg.addEventListener('click',Click_Circle_create) function Click_Circle_create(event){ //if circle clicked then don't create new circle if (event.target.nodeName === 'circle') return; const svgPoint =Get_SVG_Coordinate(svg, event.clientX, event.clientY), cX=Math.round(svgPoint.x), cY=Math.round(svgPoint.y); // add new SVG element const circle = document.createElementNS(NS, 'circle'); circle.setAttribute('cx', cX); circle.setAttribute('cy', cY); circle.setAttribute('r', 20); svg.appendChild(circle); } function Get_SVG_Coordinate(svg, x, y) { var pt = svg.createSVGPoint(); pt.x = x; pt.y = y; return pt.matrixTransform(svg.getScreenCTM().inverse()); } </script> </body> </html>

Here on the output screen, you can observe. When we click on the area then it takes coordinates point x, y and create circle on that point by appending the new child circle in the SVG element.

Hope you got the idea behind SVG and DOM translation with amazing examples.

raja
Updated on 11-Oct-2022 09:26:56

Advertisements