如何使用javascript从主svg对象动态创建svg视图框

How can I dynamically create svg viewboxes from a master svg object using javascript?

本文关键字:svg 创建 视图 动态 对象 javascript 从主 何使用      更新时间:2023-09-26

我的页面上有一个非常大且复杂的svg元素。我的目标是使svg可以打印各种尺寸,一直到绘图仪的比例。如果图形大于纸张大小,则图像需要平铺以跨越多页。理想情况下,浏览器(针对Firefox38)会为我平铺/包装svg图形,但这似乎不可能。如果我将svg图形缩放到合适的大小并打印它,任何超出页面边界的东西都会被切断。

作为这个问题的解决方案,我可以将svg拆分为多个较小的切片svg元素,并设置viewBox属性,并将切片svg的内容作为<use></use>标签,如下所示:

    <div id="SVGMasterDiv">
    <svg id="SVGMaster" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="4903.745578" height="1092.0904763600001" xml:space="preserve">
        <!-- a lot of svg here -->
    </svg>
</div>
<div id="SVGAttribObj" data-canvaswidth="2451.872789" data-canvasheight="546.0452381800001"></div>
<div id="SVGSlicesDiv">
    <svg viewbox="0 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in" style="">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="245.1872789 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="490.3745578 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="735.5618367 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="980.7491156 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="1225.9363945 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="1471.1236734 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="1716.3109523 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="1961.4982312 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
    <svg viewbox="2206.6855101 0 245.1872789 546.0452381800001" width="1.3470712411148744in" height="3in">
        <use xlink:href="#SVGMaster"></use>
    </svg>
</div>

如果我把它保存到一个html文件中,效果会很好。

问题是我需要动态地这样做——所以我在页面上有一个下拉列表,让用户指定要缩放svg的高度(以英寸为单位),以及要制作的切片数量,javascript函数创建切片svg元素。

function Coordsheet_MakeLayoutPrintable(numSlices, pageHeight){
    // This function divides the SVGMaster into slices that may be printed
    // The new elements will be placed in the same div as the SVGMaster div
    // Determine where to put the child divs
    var holderDiv = document.getElementById('SVGSlicesDiv');
    holderDiv.innerHTML = "";
    // Get the attributes saved when the SVGMaster was created
    var attribObj = document.getElementById('SVGAttribObj');
    var width = parseFloat(attribObj.getAttribute('data-canvasWidth'))
    var height = parseFloat(attribObj.getAttribute('data-canvasHeight'))
    // Make a series of containers for the svg element in the result holder div
    var blockWidth = width / numSlices;
    var pageWidth = blockWidth * pageHeight/height;
    for (var i = 0; i < numSlices; i++) {
        x = i * blockWidth;
        var s = document.createElement('svg');
        s.innerHTML = '<use xlink:href="#SVGMaster">';
        s.setAttribute("viewBox", x + " " + 0 + " " + (blockWidth) + " " + (height));
        s.setAttribute("width", blockWidth);
        s.setAttribute("height", height);
        // Viewport size (size visible)
        s.setAttribute("height", pageHeight + "in");
        s.setAttribute("width", pageWidth + "in");
        holderDiv.appendChild(s);
    }
}

这导致了上面显示的html,但由于某些原因,更新没有显示在页面上。如何让浏览器重新加载svg(或其他什么),以便更新viewBox切片?

tl;dr:为什么viewBoxsvg元素在动态生成时不进行渲染

您不能使用createElement来创建SVG元素,它只会创建html元素。您必须使用createElementNS,即

var s = document.createElementNS('http://www.w3.org/2000/svg', 'svg');