svg foreignObject的作用(文本换行,生成图片)

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
            };
        }

 

posted @ 2019-10-10 18:00  方帅  阅读(9786)  评论(0编辑  收藏  举报