用SVG创建一个表
Create a table in SVG
我正在尝试在SVG文档中创建一个类似表格的对象。目前,由于SVG没有表元素,我使用HTML解析器来遍历并转换HTML表(由用户在HTML表生成器中创建)为一组SVG对象,然后将其添加到总体SVG绘图中。我想知道是否有人能够找到一个更好的替代这种方法,如SVG表构建器?我希望使用Javascript或jquery来实现这一点。任何想法或建议将不胜感激。
我只需在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>
U可以使用这种方式:
SVG中没有"table"类型的元素,但是您可以使用"text"answers"tspan"元素实现类似的视觉和交互效果。在左边是两个这样的表格表示,顶部的是柱状布局(即用户可以选择一列中的所有文本),底部的是基于行的布局。这种方法的一个明显缺点是不能同时创建具有垂直和水平选择性的表。一个不太明显的缺陷是,创建一个表格的外观并没有赋予一个真正的表的语义质量,这不利于可访问性,也不利于丰富的交互性和导航
的例子:
<?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
我也有类似的需求,但无法找到合适的工具来自动构建SVG图像以显示表格数据(我可以通过Google找到的工具产生难以辨认或无法使用的结果),因此我构建了自己的工具。您或任何在此页面搜索此类工具的人可能会发现它很有帮助:
https://topherrhodes.com/svg-table/此工具使用CSV作为输入,因此如果您必须从HTML表转换为JavaScript对象,则可以修改脚本以将表转换为JavaScript对象,或者生成CSV作为中间步骤。
一般来说,我同意这里的其他用户提出的SVG不是显示表格数据的好格式,为了可用性和兼容性,应该尽可能选择使用实际的HTML表格。但在某些情况下,这是不可能的。
我只是想为后人补充一下我的想法。有很多相当复杂的选项,但如果你只是想让看起来像一个表格,这可能会让你开始…
//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.
这显然是粗糙的,但可能会让你开始走上正确的轨道。
我在github上发现了一个项目,它可以从JavaScript数据结构自动生成一个类似html的表:https://github.com/cocuh/SVG-Table
由于它不依赖于foreignObject,所以跨浏览器的可移植性要好得多。
下面的示例显示了SVG foreignobject,其中包含嵌套SVG元素的表格布局。这只适用于Chrome浏览器。
它包括一个HTML表格布局和一个使用div元素的flexbox布局。
这里有一个jsfield。
<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>
死灵。
问题是,当你需要一个表,它可以有无限的行和列,具有未知和可变的行高,以及在编译时未知的文本,需要调整大小以适应容器,它既不应该被剪切也不应该溢出。
幸运的是,我找到了解决办法!
不过,它需要在运行时用JavaScript设置viewBox。
适用于Firefox和Chrome。
<?xml version="1.0" standalone="yes"?>
<html>
<head>
<title>Evacuation Plan</title>
<style type="text/css">
/*<![CDATA[*/
.A4
{
width: 21cm;
height: 29.7cm;
}
/*]]>*/
</style>
</head>
<body class="A4">
<div id="positionRoot" style="position: relative;">
<div id="sizerForTable" style="position: absolute; display: block; top: 2.5cm; left: 5cm; width: 2.5cm; height: 2.5cm; background-color: hotpink;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" preserveAspectRatio="xMinYMin meet" width="100%" height="100%" >
<rect id="rectBG" x="0" y="0" width="0" height="0" fill="#FF0000" />
<foreignObject id="foTableContainer" x="0" y="0" width="100%" height="100%">
<body xmlns="http://www.w3.org/1999/xhtml">
<!--
<style type="text/css">
/*<![CDATA[*/
.testTableLayout
{
font-size: 5px;
line-height: 1em;
}
/*]]>*/
</style>
-->
<!-- also: Tabelle ausmessen - dies in Viewbox - dann verkleiners sich automatisch -->
<table id="tblTest" class="testTableLayout" style="border-collapse: collapse; border: none;" cellpadding="0" cellspacing="0">
<tr style="background-color: orange;">
<td>Row1</td>
<td>C1.2</td>
<td>Test<br />Me<br />More</td>
</tr>
<tr>
<td>Row2</td>
<td>C2.2</td>
<td>Test<!-- Me More--></td>
</tr>
<tr>
<td>Row3</td>
<td>C3.2</td>
<td>Test</td>
</tr>
<tr>
<td>Row4</td>
<td>C4.2</td>
<td>Test</td>
</tr>
<tr>
<td>Row5</td>
<td>C5.2</td>
<td>Test</td>
</tr>
<!--
-->
</table>
<script type="text/javascript">
//<![CDATA[
(function () {
var tbl = document.getElementById("tblTest");
var bg = document.getElementById("rectBG");
var nvb = ["0", "0", Math.ceil(tbl.offsetWidth).toString(), Math.ceil(tbl.offsetHeight).toString()];
bg.setAttribute("width", nvb[2]);
bg.setAttribute("height", nvb[3]);
document.getElementById("foTableContainer").ownerSVGElement.setAttribute("viewBox", nvb.join(" ") );
// console.log("newViewBox:", nvb);
// console.log("w,h:", tbl.offsetWidth, tbl.offsetHeight);
// console.log(document.getElementById("foTableContainer").ownerSVGElement.getAttribute("viewBox"));
})();
//]]>
</script>
</body>
</foreignObject>
</svg>
</div>
</div>
</body>
</html>
- 将SVG元素拖动到另一个SVG元素上
- d3日历视图:如何将所有内容放在一个svg中,而不是放在几个svg中
- 如何将这两个图表放入一个SVG中
- 部分位于另一个SVG元素下方的SVG元素
- D3-使用一个SVG点击事件来影响另一个
- Svg文本元素被另一个Svg元素重叠
- 更改 <对象> 标记的属性,该标记使用 jQuery 包含一个 SVG 元素
- 如何将 svg 图像附加到另一个 svg 图像的矩形元素
- 如何在多个位置绘制svg,在另一个svg图像的顶部
- 如何在d3,js中的另一个svg之上添加svg
- 如何通过单击命令将一个SVG路径元素变形为另一个
- 嵌套在另一个SVG元素中的SVG元素的大小为0px*0px
- Snap.load()一个svg img并为其填充颜色设置动画's子节点
- RaphaelJS:在另一个SVG元素上绘制一条路径
- 在具有类的另一个SVG元素之前插入SVG元素
- 在一个 svg 中对图表的多个容器进行 D3 缩放行为
- 我可以将页面上已经存在的svg添加到另一个svg中吗
- 从 JavaScript 中获取一个 SVG 文件作为字符串
- 我如何使用一个svg文件与许多单独的svg's在html5中
- 我如何创建一个svg精灵,然后获得每个svg的坐标