0

I've got a very large and complicated svg element on my page. My goal is to make the svg printable in a variety of sizes all the way up to plotter scale. In the event the graphic is larger than the paper size the image needs to tile to span multiple pages. Ideally the browser (targeting Firefox 38) would tile/wrap the svg graphic for me, but that doesn't seem to be possible. If I scale the svg graphic to the appropriate size and print it anything beyond the page boundary gets cut off.

As a solution to this problem I can split the svg into a number of smaller slice svg elements with viewBox attributes set and have the contents of the slice svg be a <use></use> tag like this:

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

If I save this into an html file this works great.

The problem is I need to do this dynamically-- so I have a dropdown on my page that lets the user specify a height in inches to scale the svg to, and the number of slices to make and a javascript function creates the slice svg elements.

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

This results in the html shown above, but for some reason the update isn't shown on the page. How do I make the browser reload the svg (or whatever) so that the viewBox slices update?

tl;dr: Why don't viewBox svg elements render when generated on the fly?

nickvans
  • 898
  • 13
  • 24

1 Answers1

1

You cannot use createElement to create an SVG element, that will only create html elements. You must use createElementNS instead i.e.

var s = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
Robert Longson
  • 118,664
  • 26
  • 252
  • 242
  • You beautiful human being. I've been trying to figure this out for hours and hours. Thank you so much! – nickvans May 19 '16 at 16:06