Сплит SVG на кусочки - JavaScript - PullRequest
0 голосов
/ 08 октября 2019

У меня есть большой тег svg, с большим количеством многоугольников svg, строк и текста внутри, что делает 2D-карту, которую нужно переполнить, чтобы увидеть ее в полном размере на экране, что-то вроде этого:

enter image description here

Мне нужен способ распечатать его из broswer, когда я нажимаю «print» или использую «ctrl + p», но для этого мне нужно разбить его на части и поместить в столбецмакет, так что они могут соответствовать размеру А4 для печати всего содержимого, что-то вроде этого:

enter image description here

Когда я пытаюсь напечатать, я получаю это:

enter image description here

Итак, мне нужен способ разбить это поле svg на части, чтобы подогнать страницу под печать. Есть ли способ сделать это, используя js, css, что-нибудь? Спасибо!

1 Ответ

2 голосов
/ 09 октября 2019

Нет способа сделать то, что вы хотите, с чистым CSS.

Вам понадобится Javascript для создания разделенных разделов SVG.

Вот некоторый демонстрационный код. Я оставил комментарии в коде, чтобы объяснить, как он работает.

В этом примере используется флажок для имитации «режима печати», но вы можете запускать функции разделения и разделения автоматически, при печати, прослушивая beforeprint и afterprint событий.

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