SVG内部利用foreignObject嵌入XHTML元素

<foreignObject>元素的作用是可以在其中使用具有其它XML命名空间的XML元素,换句话说借助<foreignObject>标签,我们可以直接在SVG内部嵌入XHTML元素,举个简单的例子:

<svg xmlns="http://www.w3.org/2000/svg">
<foreignObject width="120" height="50">
<body xmlns="http://www.w3.org/1999/xhtml">
<p>文字。</p>
</body>
</foreignObject>
</svg>

可以看到<foreignObject>标签里面有一个设置了xmlns="http://www.w3.org/1999/xhtml"命名空间的<body>标签,此时<body>标签及其子标签都会按照XHTML标准渲染,实现了SVG和XHTML的混合使用。

SVG forginObject实现文本自动换行

SVG要实现文本换行,往往需要手动阻断,类似下面的代码:

<svg xmlns="http://www.w3.org/2000/svg">
<text font-size="12">
<tspan x="0" y="10">一段需要word wrap</tspan>
<tspan x="0" y="26">的文字。</tspan>
</text>
</svg>

需要2<tspan>元素,这一点都不工程。虽然Chrome浏览器可以对<text>标签进行white-space:normal的强制设置,但也只是Chrome浏览器可以。

但是如果使用<foreignObject>元素,则自动换行就是小菜:

<svg xmlns="http://www.w3.org/2000/svg">
<foreignObject width="120" height="50">
<body xmlns="http://www.w3.org/1999/xhtml">
<p style="font-size:12px;margin:0;">一段需要word wrap的文字。</p>
</body>
</foreignObject>
</svg>

SVG forginObject生成图片

除了轻松实现文本换行,SVG <foreignObject>元素还有其他更高级的应用,就是可以将页面上的DOM元素轻松变成图片,原理如下:

  1. 获取对应DOM元素的outerHTML代码;
  2. 放在<foreignObject>元素中;
  3. 图片方式显示我们的SVG图形,例如:
    <img width="300" height="150" src='data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><foreignObject width="120" height="50"><body xmlns="http://www.w3.org/1999/xhtml"><p style="font-size:12px;margin:0;">一段需要word wrap的文字。</p></body></foreignObject></svg>'>
  4. 上一步的图片本质还是SVG,我们可以借助canvas drawImage()方法将图片放在画布上,然后使用canvas.toDataURL()方法转换成pngjpg图片,核心代码:
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    canvas.drawImage(img, 0, 0);
    img.src = canvas.toDataURL('image/png');

一旦我们可以把DOM元素转换成图片,我们就可以轻轻松松配合JS在前端实现网页截图功能。

之前项目中有将highcharts.js的表格转换成图片,代码如下:

        private generateTable(chartSetting: Core.ChartConfig) {
if (chartSetting.firstColColor.toLocaleLowerCase() == "rgb(255,255,254)") {
chartSetting.firstColColor = chartSetting.bgColor;
}
if (chartSetting.firstRowColor.toLocaleLowerCase() == "rgb(255,255,254)") {
chartSetting.firstRowColor = chartSetting.bgColor;
}
var tableHtml = document.createElement("table");
tableHtml.style.border = "1px solid";
tableHtml.style.borderCollapse = "collapse";
tableHtml.style.fontSize = "14px";
tableHtml.style.lineHeight = "26px"; //tableHtml.style.backgroundColor = (chartSetting.bgColor.toLocaleLowerCase().replace(")", "") + "," + (1 - chartSetting.opacityValue) + ")").replace("rgb", "rgba");
tableHtml.style.color = chartSetting.fontColor;
tableHtml.style.borderColor = chartSetting.borderColor;
tableHtml.style.fontFamily = chartSetting.fontFamily;
var tableData: any = chartSetting.chartData;
var series = [];
for (var i = 1; i < tableData[0].length - 1; i++) {
var y = tableData[0][i];
if (y == '' || y == null) {
break;
}
series.push(y);
}
for (var i = 0; i < tableData.length - 1; i++) {
var x = tableData[i][0];
if (i != 0 && (x == '' || x == null)) {
break;
}
var tr = document.createElement("TR");
tableHtml.appendChild(tr); for (var j = 0; j < tableData[i].length - 1; j++) {
if (j != 0 && (tableData[0][j] == null || tableData[0][j] == "")) {
break;
}
//var y: any = parseFloat(tableData[i][j]);
var td = document.createElement("TD");
tr.appendChild(td);
td.style.border = "1px solid " + chartSetting.borderColor;
td.style.padding = "0px 7px 0px 7px";
if (tableData[i][j] || i == 0 || j == 0) {
td.innerHTML = tableData[i][j];
} else {
td.innerHTML = "";
}
if (i != 0 && j == 0) {
td.style.backgroundColor = (chartSetting.firstColColor.toLocaleLowerCase().replace(")", "") + "," + (1 - chartSetting.opacityValue) + ")").replace("rgb", "rgba");
} else if (i == 0) {
td.style.backgroundColor = (chartSetting.firstRowColor.toLocaleLowerCase().replace(")", "") + "," + (1 - chartSetting.opacityValue) + ")").replace("rgb", "rgba");
} else {
td.style.backgroundColor = (chartSetting.bgColor.toLocaleLowerCase().replace(")", "") + "," + (1 - chartSetting.opacityValue) + ")").replace("rgb", "rgba");
}
}
}
var table_img_div = document.getElementById("table_img");
table_img_div.innerHTML = tableHtml.outerHTML.replace(/\n/g, "<br>");
var tableW = $(table_img_div).width();
var tableH = $(table_img_div).height();
var img_svg = '<svg width="' + (tableW) + 'px" height="' + tableH + 'px" xmlns = "http://www.w3.org/2000/svg" ><desc>Created with Highcharts 4.2.4</desc> <switch> <foreignObject width="' + (tableW) + '" height="' + tableH + '" requiredFeatures = "http://www.w3.org/TR/SVG11/feature#Extensibility"><body style="margin:0" xmlns="http://www.w3.org/1999/xhtml">' + tableHtml.outerHTML
+ ' </body></foreignObject><text font-size="10" font-family="Verdana"><tspan x= "10" y= "10" > 请使用其他浏览器,</tspan><tspan x= "10" y= "20" > 以正常显示表格。</tspan> </text></switch></svg>';
img_svg = img_svg.replace(/\n/g, "<br/>");
return {
svg: img_svg,
width: tableW,
height: tableH
};
}

svg foreignObject的作用(文本换行,生成图片)的更多相关文章

  1. 小程序canvas文本换行生成图片

    一.图片透明及旋转 let ctx = wx.createCanvasContext('shareImg') ctx.drawImage('../../../' + res[0].path, 0, 0 ...

  2. 文本换行word-wrap、word-break与white-space

    本文同步至微信公众号:http://mp.weixin.qq.com/s?__biz=MzAxMzgwNDU3Mg==&mid=401671055&idx=1&sn=b88c9 ...

  3. CSS学习笔记:文本换行显示(word-wrap)

    在CSS3中新定义了文本换行属性,word-wrap: nomal属性值表示控制连续文本换行. break-word属性值表示内容将在边界内换行.如果需要,词内换行(word-break)也会发生. ...

  4. Vue插值文本换行问题

    问题背景: 后端返回的字符串带有\n换行符,但Vue将其插值渲染成div内部文本后,文本并不换行,换行符显示为一个空格. 目标: 让文本在换行符处换行. 解决方法: 思路:实现文本换行有两种方法,一是 ...

  5. arcgis api 3.x for js 解决 textSymbol 文本换行显示(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  6. wbr 文本换行规则标签

    <wbr/>标签规定在文本中的何处适合添加换行符.如果文本太长,浏览器可能会在错误的位置换行,那么可以使用<wbr/>标签来添加单词换行时机. Talk is cheap. S ...

  7. Asp.Net中文本换行

    Asp.Net中文本换行 VB.NET Function HtmlCode(ByVal fString)        If fString <> "" Then    ...

  8. Eclipse console文本换行

    Eclipse换行主要有3个方面 格式化时编辑器文本换行 源代码注释文本换行 Eclipse控制台console显示文本换行 1和2参考 http://hi.baidu.com/ae6623/item ...

  9. clipboard让复制的文本换行

    https://clipboardjs.com/dist/clipboard.min.js 用clipboard实现复制时, 想让复制的文本换行, 有两咱方法: 第一种, HTML实现: <!- ...

随机推荐

  1. HDU - 1392 Surround the Trees (凸包)

    Surround the Trees:http://acm.hdu.edu.cn/showproblem.php?pid=1392 题意: 在给定点中找到凸包,计算这个凸包的周长. 思路: 这道题找出 ...

  2. 杭电多校 hdu6627 equation

    http://acm.hdu.edu.cn/showproblem.php?pid=6627 题意:解绝对值方程并统计解的个数. 解法:签到题,直接模拟小学数学学的零点分段法即可.(数据多直接cin, ...

  3. CF1007B Pave the Parallelepiped 容斥原理

    Pave the Parallelepiped time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  4. 一起MySQL时间戳精度引发的血案

    写在前面 最近工作中遇到两例mysql时间戳相关的问题,一个是mysql-connector-java和msyql的精度不一致导致数据查不到:另一例是应用服务器时区错误导致数据查询不到.通过这篇文章, ...

  5. Webstorm 的设置

    背景色

  6. HDFS之Qurom Journal Manager(QJM)实现机制分析

    前言 1.1背景 自从hadoop2版本开始,社区引入了NameNode高可用方案.NameNode主从节点间需要同步操作日志来达到主从节点元数据一致.最初业界均通过NFS来实现日志同步,大家之所以选 ...

  7. 02 (H5*) Vue第二天

    目录: 1:全局过滤器的使用 2:局部过滤器 3:自定义键盘码 4:自定义指令 5:自定义私有指令 6:Vue生命周期. 7:网络请求 1:全局过滤器的使用 Vue.filter("msgF ...

  8. 40 (OC)* 数据库常见sql语句

    1:增加INSERT INTO t_student (name, age) VALUES ('liwx', 18);2:删除DELETE FROM t_student WHERE name = 'li ...

  9. Android四大组件之服务的两种启动方式详解

    Service简单概述 Service(服务):是一个没有用户界面.可以在后台长期运行且可以执行操作的应用组件.服务可由其他应用组件启动(如:Activity.另一个service).此外,组件可以绑 ...

  10. validator 自动化校验

    温馨提示 请收藏再看.此文篇幅太长,你短时间看不完:此文干货太多,错过太可惜. 示例代码可以关注逸飞兮(公众号)回复jy获取. 收获 讲解详细:能让你掌握使用 hibernate-validator ...