Reputation: 35
I have a big svg tag, with lots of svg polygons, line, text inside it making a 2D map, which need overflow to see it full size on screen, something like that:
I need a way to print it from broswer when I click "print" or use "ctrl + p", but for that i need to break it into pieces and put then on column layout, so they can fit on A4 size to print the entire content, something like that:
When I try to print i get this:
So, I need a way to break this svg field into pieces to fit the page to print. Is there any way to do that, using js, css, anything? Thank you!
Upvotes: 0
Views: 3864
Reputation: 101820
There is no way to do what you want with pure CSS.
You'll need Javascript to create the split sections of the SVG.
Here's some demonstration code. I've left comments in the code to explain how it works.
The example uses a checkbox to simulate "print mode" but you could run the split and unsplit functions automatically, when printing, by listening to the beforeprint
and afterprint
events.
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeprint
function splitSVGs(splitWidth) {
let splittables = document.querySelectorAll(".splittable");
splittables.forEach(function(svgElem) {
// Get starting size of the original SVG now
const computed = getComputedStyle(svgElem);
const width = parseInt(computed.width, 10);
const height = parseInt(computed.height, 10);
const vB = svgElem.viewBox.baseVal;
// Get the viewBox of the SVG also
const bbox = (svgElem.getAttribute("viewBox") !== null) ? {x:vB.x, y:vB.y, width:vB.width, height:vB.height}
: {x:0, y:0, width, height};
// Hide the original SVG
svgElem.classList.add("hide");
// Create a temporary div element to hold our generated sections
const div = document.createElement("div");
div.classList.add("sections");
svgElem.insertAdjacentElement('afterend', div);
let remainingWidth = width;
while (remainingWidth > 0) {
const sectionWidth = Math.min(splitWidth, remainingWidth);
// Convert sectionWidth relative to viewBox
bbox.width = sectionWidth * bbox.height / height;
// Create an SVG element to contain one section of the split
const section = document.createElementNS("http://www.w3.org/2000/svg", "svg");
section.setAttribute("width", sectionWidth);
// Add a viewBox that shows the area of the original that we want to see in this section
section.setAttribute("viewBox", [bbox.x, bbox.y, bbox.width, bbox.height].join(' '));
// Add a <use> element to the section SVG that references the original
const use = document.createElementNS("http://www.w3.org/2000/svg", "use");
use.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", '#'+svgElem.id);
use.setAttribute("width", vB.width);
use.setAttribute("height", vB.height);
section.appendChild(use);
// Add this section SVG to the sections div
div.appendChild(section);
// How much of the original SVG width is left?
remainingWidth -= splitWidth;
// Update bbox so the next SVG will show the next section of the original
bbox.x += bbox.width;
}
});
}
function unsplitSVGs() {
// Get rid of the generated sections
const sections = document.querySelectorAll(".sections");
sections.forEach(function(div) {
div.remove();
});
// Unhide all the original SVGs
const splittables = document.querySelectorAll(".splittable");
splittables.forEach(function(svgElem) {
svgElem.classList.remove("hide");
});
}
document.getElementById("print-mode").addEventListener("change", function(evt) {
if (evt.target.checked) {
splitSVGs(600);
} else {
unsplitSVGs();
}
});
svg {
background: linen;
}
svg#test {
width: 2960px;
height: 80px;
border: solid 2px black;
}
/* Hide while still keeping the contents visible to our section SVGs */
.hide {
position: absolute;
top: -9999px;
}
.sections svg {
border: solid 2px black;
}
.sections svg:not(:first-child) {
border-left: dashed 2px black;
}
.sections svg:not(:last-child) {
border-right: dashed 2px black;
}
<p>
<input type="checkbox" id="print-mode">
<label for="print-mode"> Simulate print mode (split the SVG)</label>
</p>
<svg viewBox="0 0 1480 40" id="test" class="splittable">
<text x="10" y="30" font-size="30px">We choose to go to the Moon in this decade and do the other things, not because they are easy, but because they are hard.</text>
</svg>
Upvotes: 3