Search code examples
javascriptsvgscale

How to convert the value of the area of a SVG object into m2


I am using the math formulas to get the area of a circle or a rectangle of a SVG object. For the area of a polygon I use this formula.

But the values are in the viewbox scale and I want to convert it to square meters. For example, a rectangle object has the width and height properties. So it is just:

element.width x element.height = area

Considering the viewbox of a svg = "0 0 100 100" for example, and having a line object in svg that is used as a reference of a scale like in this image sample:

sample

How can I convert the area value to a square meters? It is necessary to use the viewbox or just the definition that 1m is the object line width? I do not want to use the library d3.js. Thank you.

UPDATE: enter image description here

For the rectangule we must use the width and height and for the circle the radius. In both cases it is easy to convert the radius, height and width into meters. But in a polygon, what is used to calculate the areas are the vertices (points) with the values x and y axis. How to make the "translation" into meters?

NEW UPDATE

I still am unable to calculate well the polygons. I posted an example here: running example

No problems for circles and squares/rectangules. But for some reason it does not work for irregular polygon. Funny thing is that it does work if i create a polygon that is a square. Any suggestions to solve this mistery? Thank you.


Solution

  • First you need to know how long is a meter in the svg element:

    let meter = m.getTotalLength();
    

    Next you get the bounding box of the rect. This is returning an svg rect with a position (x,y) a width and a height. You will need only the width and a height:

    let rect = the_rect.getBBox();
    

    Now you can calculate the equivalent in meters of the width and height of the rect:

    let w = rect.width / meter;
    let h = rect.height / meter;
    

    Finally you can calculate the area of the rect

    let area = w * h;
    

    This is an working example:

    // get the length of the line representing one meter
    let meter = m.getTotalLength();
    // get the bounding box of the rect. This is returning an svg rect with a position (x,y) a width and a height. 
    let rect = the_rect.getBBox();
    
    //calculate the equivalent in meters of the width and height
    let w = rect.width / meter;
    let h = rect.height / meter;
    //calculate thge area in merers
    let area = w * h;
    
    console.log("area:",area)
    svg{border:solid; width:300px}
    <svg viewBox="0 0 100 100">
      <rect id="the_rect" x="10" y="10" width="30" height="50" stroke="black" fill="#cab" />
    
      <path id="m" d="M50,70H90" stroke="black" />
      <text text-anchor="middle" dy="-5">
        <textPath xlink:href="#m" startOffset="50%">1 m</textPath>
      </text>
    
    </svg>

    UPDATE

    someone is commenting

    Just note that getBBox "does not account for any transformation applied to the element or its parents" (just in case somebody needs it for transformed shape)

    In the case the transformation applied is only a translation the transformation is irrelevant since you are using only the width and the height. If the transformation implies scaling you will need to wrap the shape in a group and get the bounding box of the group. If the transformation implies skewing you already have a lozenge not a rect so for this you will need a different approach.

    The main idea about this answer is not showing you how to get the area of any king of polygon (which you know), but how to get the size from svg units to meters.