Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a table in SVG

I'm trying to create a table-like object within an SVG document. Currently, due to the fact that SVG does not have a table element, I am using an HTML parser to go through and convert an HTML table, (created by the user in an HTML table Builder), to a group of SVG objects, and then adding that to my overall SVG drawing. I was wondering if any one was able to find a better alternative to this method, such as an SVG table builder? I'm looking to accomplish this using Javascript or jquery. Any ideas or suggestions would be appreciated.

like image 708
RestingRobot Avatar asked Aug 08 '11 18:08

RestingRobot


4 Answers

I would simply embed a real table in my SVG:

<?xml version="1.0" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg">
  <foreignObject x="10" y="10" width="100" height="150">
    <body xmlns="http://www.w3.org/1999/xhtml">
      <table><!-- ... --></table>
    </body>
  </foreignObject>
  <!-- ... -->
</svg>
like image 100
Phrogz Avatar answered Nov 03 '22 08:11

Phrogz


U can use this way:

There are no 'table'-type elements in SVG, but you can achieve a similar visual and interactive effect using the 'text' and 'tspan' elements. On the left are 2 such tabular representations, the top one with columnar layout (that is, the user can select all the text in a column), and the bottom table with row- based layout. An obvious disadvantage to this approach is that you cannot create a table with both vertical and horizontal selectivity. A less obvious flaw is that creating a tabular appearance does not confer the semantic qualities of a real table, which is disadvantageous to accessibility and is not conducive to rich interactivity and navigation

Example:

<?xml version='1.0' standalone='no'?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN'
  'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg width='100%' height='100%' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>

   <title>SVG Table</title>

   <g id='columnGroup'>
      <rect x='65' y='10' width='75' height='110' fill='gainsboro'/>
      <rect x='265' y='10' width='75' height='110' fill='gainsboro'/>

      <text x='30' y='30' font-size='18px' font-weight='bold' fill='crimson'>
         <tspan x='30' dy='1.5em'>Q1</tspan>
         <tspan x='30' dy='1em'>Q2</tspan>
         <tspan x='30' dy='1em'>Q3</tspan>
         <tspan x='30' dy='1em'>Q4</tspan>
      </text>

      <text x='100' y='30' font-size='18px' text-anchor='middle'>
         <tspan x='100' font-weight='bold' fill='crimson'>Sales</tspan>
         <tspan x='100' dy='1.5em'>$ 223</tspan>
         <tspan x='100' dy='1em'>$ 183</tspan>
         <tspan x='100' dy='1em'>$ 277</tspan>
         <tspan x='100' dy='1em'>$ 402</tspan>
      </text>

      <text x='200' y='30' font-size='18px' text-anchor='middle'>
         <tspan x='200' font-weight='bold' fill='crimson'>Expenses</tspan>
         <tspan x='200' dy='1.5em'>$ 195</tspan>
         <tspan x='200' dy='1em'>$ 70</tspan>
         <tspan x='200' dy='1em'>$ 88</tspan>
         <tspan x='200' dy='1em'>$ 133</tspan>
      </text>

      <text x='300' y='30' font-size='18px' text-anchor='middle'>
         <tspan x='300' font-weight='bold' fill='crimson'>Net</tspan>
         <tspan x='300' dy='1.5em'>$ 28</tspan>
         <tspan x='300' dy='1em'>$ 113</tspan>
         <tspan x='300' dy='1em'>$ 189</tspan>
         <tspan x='300' dy='1em'>$ 269</tspan>
      </text>
   </g>
</svg>

Source: http://svg-whiz.com/svg/table.svg

like image 23
jacksonfdam Avatar answered Nov 03 '22 09:11

jacksonfdam


I had a similar need and was not able to find a suitable tool for automatically building an SVG image to display tabular data (the tools I could find via Google produced illegible or otherwise unusable results) so I built my own. You or anyone else who lands on this page while searching for such a tool may find it helpful:

https://topherrhodes.com/svg-table/

This tool uses a CSV as input, so if you have to go from an HTML table you could modify the script to convert the table to a JavaScript object, or generate a CSV as an intermediate step.

Generally, I agree with the other users here who have brought up how SVG is not a good format for displaying tabular data and that for usability and compatibility you should opt to use an actual HTML table whenever possible. But there may be certain cases where that's not possible.

like image 4
Topher Rhodes Avatar answered Nov 03 '22 07:11

Topher Rhodes


I just wanted to add my thoughts on this for posterity. There are a lot of fairly complicated options out there but if you just want something which looks like a table, this might get you started...

//assuming you have a table with an ID of src_table
var my_svg = '<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" id="svg_table" width="'+$("#src_table").width()+'px" height="'+$("#src_table").height()+'px">'
var table_offset = $('#src_table').offset();
$('#src_table').find('td').each(function() {
        //Add a rectangle for each <td> in the same place in SVG as the <td> is in relation to the top left of where the table is on page
        my_svg += '<rect x="'+(this_offset.left - table_offset.left)+'" y="'+(this_offset.top - table_offset.top)+'" width="'+$(this).width()+'" height="'+$(this).height()+'" stroke="black" stroke-width="'+$(this).css('border-width').replace('px','')+'"/>';

       //Text is assumed to be in a <p> tag. If it's not, just use the .html() of the <td> element
       (this).children('p').each(function(){
                t_offset = $(this).offset();
                var this_text = '<text x="'+(t_offset.left - table_offset.left)+'" y="'+(t_offset.top - table_offset.top)+'"  style="font-size:'+$(this).css('font-size')+'; fill: #ffffff">';
                    // Look for <br> tags and split them onto new lines.
                    var this_lines = $(this).html().split('<br>');
                    for(var i=0;i<this_lines.length;i++){
                        this_text += '<tspan x="'+(t_offset.left - table_offset.left)+'" dy="'+$(this).css('font-size')+'">'+this_lines[i]+'</tspan>';
                    }
            this_text += '</text>';
            my_svg +=  this_text;
        })
    }
});
my_svg += '</svg>';

//Either append my_svg to a div or pass the code onto whatever else you need to do with it.

This is obviously rough but might get you started down the right track.

like image 2
jperry1147 Avatar answered Nov 03 '22 07:11

jperry1147