Posterize SVG

by mgoetzke

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.4.0/svg.js"></script>
<body>
  <div id="pages" onclick="print()">


  </div>
  <div id="full-svg">
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="3299" height="801" viewBox="-1461 -5 3299 801" version="1.1">
      <defs>
        <marker id="sequenceflow-end" viewBox="0 0 20 20" refX="11" refY="10" markerWidth="10" markerHeight="10" orient="auto">
          <path d="M 1 5 L 11 10 L 1 15 Z" style="fill: black; stroke-width: 1px; stroke-linecap: round; stroke-dasharray: 10000, 1;"></path>
        </marker>
        <marker id="messageflow-start" viewBox="0 0 20 20" refX="6" refY="6" markerWidth="20" markerHeight="20" orient="auto">
          <circle cx="6" cy="6" r="3.5" style="fill: white; stroke-width: 1px; stroke-linecap: round; stroke-dasharray: 10000, 1; stroke: black;"></circle>
        </marker>
        <marker id="messageflow-end" viewBox="0 0 20 20" refX="8.5" refY="5" markerWidth="20" markerHeight="20" orient="auto">
          <path d="m 1 5 l 0 -3 l 7 3 l -7 3 z" style="fill: white; stroke-width: 1px; stroke-linecap: butt; stroke-dasharray: 10000, 1; stroke: black;"></path>
        </marker>
        <marker id="association-start" viewBox="0 0 20 20" refX="1" refY="10" markerWidth="10" markerHeight="10" orient="auto">
          <path d="M 11 5 L 1 10 L 11 15" style="fill: none; stroke-width: 1.5px; stroke-linecap: round; stroke-dasharray: 10000, 1; stroke: black;"></path>
        </marker>
        <marker id="association-end" viewBox="0 0 20 20" refX="12" refY="10" markerWidth="10" markerHeight="10" orient="auto">
          <path d="M 1 5 L 11 10 L 1 15" style="fill: none; stroke-width: 1.5px; stroke-linecap: round; stroke-dasharray: 10000, 1; stroke: black;"></path>
        </marker>
        <marker id="conditional-flow-marker" viewBox="0 0 20 20" refX="-1" refY="10" markerWidth="10" markerHeight="10" orient="auto">
          <path d="M 0 10 L 8 6 L...

CSS

@media print {
  @page {
    size: A4 landscape;
    margin: 5mm;
   }

   .page {
   }
   
   .page svg {
   }
}

body {
  width: 287mm;
  position:relative;
}

.page {
  position: relative;
  padding: 40px;
  page-break-inside: avoid;
  xbackground: green;
 }

.page svg {
   xborder: 2px solid yellow;
 }

/* Shows current row / column of page when being glued together */
.page-position {
  position: absolute;
  top: 10px;
  left: 10px;
  opacity: 1;
  padding: 4px;
  color: darkgray;
  background: rgba(255, 255, 255, 1);
  border: 1px solid gray;
  font-family: Sans-serif;
  font-size: 8px;
}

JavaScript

var ZOOM_OUT_FACTOR = 4 // The higher the more data will be shown per page
var OVERLAP = 100 // Amount of 'pixels' each page stil shows the preceding pages content in x and y

var PAGE_SIZE_WIDTH = 297
var PAGE_SIZE_HEIGHT = 210

var svg = document.querySelector('#full-svg > svg');
var pages = document.querySelector('#pages')

var el = new SVG(svg)

var fullViewBox = el.viewbox()

var maxWidth = PAGE_SIZE_WIDTH * ZOOM_OUT_FACTOR;
var maxHeight = PAGE_SIZE_HEIGHT * ZOOM_OUT_FACTOR;

var printWidth = '' + PAGE_SIZE_WIDTH * 3 + 'px';
var printHeight = '' + PAGE_SIZE_HEIGHT * 3 + 'px';

var overlapX = OVERLAP;
var overlapY = OVERLAP;

svg.setAttribute('width', maxWidth.toString());
svg.setAttribute('height', maxHeight.toString());

var iteration = 0;
var svgPages = []

var yIndex = 1;

for (var y = fullViewBox.y;; yIndex++) {
  console.log('y', y);

  var xIndex = 1;

  for (var x = fullViewBox.x;; xIndex++) {
    console.log('x', x);

    var currentPageViewBox = {
      x: x,
      y: y,
      width: maxWidth,
      height: maxHeight
    }
    el.viewbox(currentPageViewBox)

    svgPages.push({
      x: xIndex,
      y: yIndex,
      svg: el.svg()
    })

    x += maxWidth

    if (x >= fullViewBox.x + fullViewBox.width)
      break

    x -= overlapX;
  }


  y += maxHeight

  if (y >= fullViewBox.y + fullViewBox.height)
    break

  y -= overlapY
}

document.querySelector('#full-svg').setAttribute('style', 'display:none')

var pageIndex = 1;

svgPages.forEach(function(pageContent) {
  var page = document.createElement('div')
  var indexedPageClass = 'page-' + pageIndex;
  page.setAttribute('class', 'page ' + indexedPageClass)
  page.innerHTML = pageContent.svg
  pages.appendChild(page)

  var svgEl = document.querySelector( '.'+indexedPageClass + ' svg' )
  svgEl.setAttribute('width', printWidth)
  svgEl.setAttribute('height',printHeight)

  
  var pos = document.createElement('div')
  pos.setAttribute('class', 'page-position')
  pos.innerHTML = '<span...