在SVG中创建一个表

时间:2011-08-08 18:47:37

标签: javascript jquery dom svg

我正在尝试在SVG文档中创建一个类似于表的对象。目前,由于SVG没有表元素,我使用HTML解析器将HTML表(由HTML表生成器中的用户创建)转换为一组SVG对象,并且然后将其添加到我的整体SVG绘图中。我想知道是否有人能够找到更好的替代方法,例如SVG表构建器?我希望使用Javascript或jquery来实现这一目标。任何想法或建议将不胜感激。

6 个答案:

答案 0 :(得分:24)

我只想在我的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>

答案 1 :(得分:14)

U可以这样使用:

SVG中没有'table'类型元素,但您可以使用'text'和'tspan'元素实现类似的视觉和交互效果。左边是2个这样的表格表示,最上面的一个是柱状布局(也就是说,用户可以选择列中的所有文本),而底部表格是基于行的布局。这种方法的一个明显缺点是您无法创建具有垂直和水平选择性的表。一个不太明显的缺陷是,创建表格外观并不会赋予真实表格的语义质量,这对可访问性不利,并且不利于丰富的交互性和导航

示例:

<?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>

来源:http://svg-whiz.com/svg/table.svg

答案 2 :(得分:2)

我只是想为后人添加我的想法。那里有很多相当复杂的选项,但是如果你只是想要像桌子那样看起来的东西,这可能会让你开始......

//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.

这显然很粗糙,但可能会让你开始走上正轨。

答案 3 :(得分:2)

我也有类似的需求,无法找到合适的工具来自动构建SVG图像以显示表格数据(我可以通过Google找到的工具产生了难以辨认或无法使用的结果),所以我建立了自己的工具。您或其他在搜索此类工具时进入此页面的人可能会发现有帮助:

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

此工具使用CSV作为输入,因此,如果您必须从HTML表中移出,则可以修改脚本以将表转换为JavaScript对象,或生成CSV作为中间步骤。

通常,我同意这里的其他用户的意见,他们提出了SVG如何不是一种用于显示表格数据的好格式,并且出于可用性和兼容性的考虑,您应该尽可能选择使用实际的HTML表。但是在某些情况下这是不可能的。

答案 4 :(得分:0)

这是一个显示SVG foreignobject的示例,其中包含嵌套SVG元素的表格布局。它只适用于Chrome。

它包含HTML table布局和使用div元素的flexbox布局。

jsfiddle是here

<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <g id="shape">
            <rect x="0" y="0" rx="5" ry="5" width="100%" height="100%" fill="inherit" />
            <circle cx="50%" cy="50%" r="8" fill="yellow" />
        </g>
    </defs>
    <foreignobject width="100%" height="50px" y="0">

        <body xmlns="http://www.w3.org/1999/xhtml">
            <table width="100%">
                <tr>
                    <td colspan="3">
                        <div style="height:20px">
                            <svg>
                                <use xlink:href="#shape" fill="CornflowerBlue" />
                            </svg>
                        </div>
                    </td>
                </tr>
                <tr>
                    <td>
                        <div style="height:20px">
                            <svg>
                                <use xlink:href="#shape" fill="SlateBlue" />
                            </svg>
                        </div>
                    </td>
                    <td>
                        <div style="height:20px">
                            <svg>
                                <use xlink:href="#shape" fill="SlateBlue" />
                            </svg>
                        </div>
                    </td>
                    <td>
                        <div style="height:20px">
                            <svg>
                                <use xlink:href="#shape" fill="SlateBlue" />
                            </svg>
                        </div>
                    </td>
                </tr>
            </table>
        </body>
    </foreignobject>
    <foreignobject width="100%" height="50px" y="60">

        <body xmlns="http://www.w3.org/1999/xhtml">
            <div style="display:flex;flex-direction:column">
                <div>
                    <div style="height:20px;padding:2px">
                        <svg>
                            <use xlink:href="#shape" fill="orange" />
                        </svg>
                    </div>
                </div>
                <div style="display:flex;flex-direction:row;align-items:stretch">
                    <div style="width:33.333%;height:20px;padding:2px">
                        <svg>
                            <use xlink:href="#shape" fill="forestgreen" />
                        </svg>
                    </div>
                    <div style="width:33.333%;height:20px;padding:2px">
                        <svg>
                            <use xlink:href="#shape" fill="forestgreen" />
                        </svg>
                    </div>
                    <div style="width:33.333%;height:20px;padding:2px">
                        <svg>
                            <use xlink:href="#shape" fill="forestgreen" />
                        </svg>
                    </div>
                </div>
            </div>
        </body>
    </foreignobject>
</svg>

答案 5 :(得分:0)

I found a project on github which automatically generates an HTML-like table from a JavaScript data structure: https://github.com/cocuh/SVG-Table

Since it does not rely on foreignObject, it's portability across browsers is much better.