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. POJ-2155-Matrix二位树状数组应用

    题目: 一个只有0和1构成的二维平面,给你两种指令,一种是区间的更新,即0变为1,1变为0:一种是查询一个点是1还是0: 由于是二进制,所以每次更新在相应的点上加一,最后对2取余即可. 至于二维的树状 ...

  2. 最短路算法 Dijkstra 入门

    dijkstra算法 是一种单源点最短路算法求出一个点到其他所有点的最短路. 给你这样的一个图,需要求出1号点到其他点的最短距离是多少. 首先我们开一个数组 d[N],d[x] 代表着从起点出发到x点 ...

  3. 告别组件之教你使用原生js和css写移动端轮播图

    在工作中由于项目需要要写一个轮播图,本想使用组件直接调用实现快速开发,但是一想到自己经常使用组件但是让自己手写的话确实一点都不会. 一个不会手写组件的前端程序员不是一个好程序员!于是打算自己手写一个. ...

  4. nginx部署成功却没有办法访问

    1.首要想到的问题是防火墙没关 注意:因为centos7.0默认不是使用iptables方式管理,而是firewalld方式.CentOS6.0防火墙用iptables管理. 2.解决: ①首先查看防 ...

  5. maven引入jar包冲突问题

    1.原因 使用maven过程中,经常会遇到jar包重复加载或者jar包冲突的问题,但是有些jar包是由于maven加载了其他jar包自动引入的,并非自己主动添加的,导致和自己添加的jar包版本冲突 举 ...

  6. apache ignite系列(一): 简介

    apache-ignite简介(一) 1,简介 ​ ignite是分布式内存网格的一种实现,其基于java平台,具有可持久化,分布式事务,分布式计算等特点,此外还支持丰富的键值存储以及SQL语法(基于 ...

  7. Spring Boot 面试题总结

    1.什么是spring boot 答案:springboot是用来简化spring应用的初始搭建和开发过程,使用特定的配置文件来配置,例如application.properties,简化来maven ...

  8. django配置静态文件的两种方法

    方法一:按照django配置静态文件的方法,可以在APP应用目录下创建一个static的文件夹,然后在static文件夹下创建一个和APP同名的文件夹,如我有一个blog的django项目,在下面有一 ...

  9. [VB.NET Tips]ParamArray参数数组

    ParamArray参数数组,可以理解为传递给方法的多余的参数全都存放在这个数组中. ParamArray只能是ByVal按值传递,不能是可选参数,而且只能做为方法定义的最后一个参数. 非常类似于Py ...

  10. Laravel 从入门到精通 创建并运行一个新的 Laravel 项目

    创建一个新的 Laravel 项目 正如官方文档所言,有两种方式可以创建一个新的 Laravel 项目,这两种创建方式都是从命令行执行的:第一种是通过全局的 Laravel 安装器,另一种是通过 Co ...