У меня есть большие svg-рисунки с неизвестными размерами в начале. Я хочу напечатать их на нескольких страницах; но количество страниц изначально не известно. Поэтому я должен выбрать количество страниц в Javascript после того, как я определю размер рисунка и добавлю элементы svg соответственно.
Есть хороший пример https://codepen.io/anon/pen/roYXVJ, который представляет собой «статический» тайлинг, т.е. размер и количество страниц фиксируются заранее. Упрощенная версия кода (без стрелок и букв индекса) выглядит следующим образом:
<figure class = "svg-container">
<!-- The actual graphic is a 3:2 image
which will be wrapped in a scrolling
container on screen. -->
<svg class = "screen" width = "18in" height = "12in"
viewBox = "0 0 1800 1200">
<g id = "graphic"><!--
Actual graphic goes here. I'm using a script to generate it.
--></g>
</svg>
<!-- For printing in landscape mode,
the graphic is divided into four
overlapping quadrants which will
each fit on a letter/A4 page
without scaling. The 1000*700 viewBox
is equivalent to 10in*7in of the
onscreen dimensions. -->
<svg class = "print landscape" viewBox = "0 0 1000 700">
<use xlink:href = "#graphic" />
</svg>
<svg class = "print landscape" viewBox = "800 0 1000 700">
<use xlink:href = "#graphic" />
</svg>
<svg class = "print landscape" viewBox = "0 500 1000 700">
<use xlink:href = "#graphic" />
</svg>
<svg class = "print landscape" viewBox = "800 500 1000 700">
<use xlink:href = "#graphic" />
</svg>
<!-- For printing in portrait mode,
the graphic is scaled down slightly
to fit on two pages. Again,
the content of each page will
overlap slightly. -->
<svg class = "print portrait" viewBox = "0 0 1000 1200">
<use xlink:href = "#graphic" />
</svg>
<svg class = "print portrait" viewBox = "800 0 1000 1200">
<use xlink:href = "#graphic" />
</svg>
</figure>
<script>
var doc = document;
var g = doc.getElementById("graphic");
var svgNS = g.namespaceURI;
var r, t;
for (var i=0; i<18; i++){
for (var j=0; j<12; j++) {
r = doc.createElementNS(svgNS, "rect");
r.setAttribute("width", "80");
r.setAttribute("height", "80");
r.setAttribute("x", (i*100 + 10));
r.setAttribute("y", (j*100 + 10));
r.style.setProperty("fill-opacity", ((i*j + 1)%20)/20, null);
g.insertBefore(r, null);
t = doc.createElementNS(svgNS, "text");
t.setAttribute("x", (i*100 + 50));
t.setAttribute("y", (j*100 + 50));
t.setAttribute("class", "diagram")
t.textContent = [i,j];
g.insertBefore(t, null);
}
}
</script>
Итак, я пытаюсь заменить
<svg class = "print landscape"... />
статические определения с такими динамическими определениями внутри скрипта: Обновлено: я исправляю некоторые определения и добавляю недостающие. Обновленные динамические определения:
var printLandscape = document.createElementNS(svgNS, "svg");
printLandscape.setAttribute("viewBox", " 800 500 1000 700");
printLandscape.setAttribute("orientation", "landscape");
printLandscape.setAttribute("xlink:href", "#graphic");
printLandscape.setAttribute("class", "print landscape")
g.insertBefore(printLandscape, null);
Но это (ЕЩЕ) не работает. Каким будет правильный способ динамического получения аналогичных результатов?
После некоторого исследования я понял, что xlink: href не является атрибутом svg, поскольку он используется функцией «использовать» (?). Итак, должен быть определен другой элемент использования, указывающий на xlink: href. Кроме того, printLanscape должен быть частью контейнера "figure". Окончательные определения следующие:
var doc = document;
var g = doc.getElementById("graphic");
var f = doc.getElementById("mafigure");
var svgNS = g.namespaceURI;
var printLandscape = document.createElementNS(svgNS, "svg");
var useElem = document.createElementNS(svgNS, 'use');
printLandscape.setAttributeNS(svgNS,"class", "print landscape")
printLandscape.setAttributeNS(svgNS, "viewBox", " 800 500 1000 700");
useElem.setAttributeNS(svgNS, 'xlink:href', '#graphic');
printLandscape.appendChild(useElem);
f.insertBefore(printLandscape, null);
Теперь, с этими определениями, у меня появилась четвертая страница в мозаике, но она пуста. При связывании выходных данных со страницей плитки должна быть еще какая-то ошибка или что-то отсутствует.
Обновлено: Вот полный тестовый пример. HTML-документ со встроенным svg и javascript. Он обеспечивает 4-страничную статическую мозаику. Я взял четвертое определение статической страницы и попытался реализовать определение динамической плитки в Javascript.
Итак, теперь он правильно печатает три страницы. Есть четвертая страница, но пустая, без содержания.
<html>
<head>
<style>
symbol, use, svg {
overflow: visible;
}
rect {
stroke: navy;
}
/* Screen styles */
figure.svg-container {
display: block;
overflow: scroll;
max-width: 90vw;
max-height: 90vh;
border:gray solid thin;
}
svg.print {
display: none;
}
@media print{
figure.svg-container {
display: inline;
overflow: auto;
border: none;
}
svg.screen {
display: none;
}
svg.print {
overflow: hidden;
border: thin lightgray solid;
padding: 0.5em;
-moz-box-sizing: border-box;
box-sizing: border-box;
page-break-inside: avoid;
break-inside: avoid;
}
}
@media print and (orientation: landscape){
svg.print.landscape {
display: block;
height: 7in;
width: 10in;
}
}
@media print and (orientation: portrait){
svg.print.portrait {
display: block;
height: 9in;
width: 7.5in;
}
}
</style>
<figure class = "svg-container" id = "mafigure">
<!-- The actual graphic is a 3:2 image
which will be wrapped in a scrolling
container on screen. -->
<svg class = "screen" width = "18in" height = "12in"
viewBox = "0 0 1800 1200">
<g id = "graphic"><!--
Actual graphic goes here. I'm using a script to generate it.
--></g>
</svg>
<!-- For printing in landscape mode,
the graphic is divided into four
overlapping quadrants which will
each fit on a letter/A4 page
without scaling. The 1000*700 viewBox
is equivalent to 10in*7in of the
onscreen dimensions. -->
<svg class = "print landscape" viewBox = "0 0 1000 700">
<use xlink:href = "#graphic" />
</svg>
<svg class = "print landscape" viewBox = "800 0 1000 700">
<use xlink:href = "#graphic" />
</svg>
<svg class = "print landscape" viewBox = "0 500 1000 700">
<use xlink:href = "#graphic" />
</svg>
<!-- For printing in portrait mode,
the graphic is scaled down slightly
to fit on two pages. Again,
the content of each page will
overlap slightly. -->
<svg class = "print portrait" viewBox = "0 0 1000 1200">
<use xlink:href = "#graphic" />
</svg>
<svg class = "print portrait" viewBox = "800 0 1000 1200">
<use xlink:href = "#graphic" />
</svg>
</figure>
<script>
var r, t;
var doc = document;
var g = doc.getElementById("graphic");
var f = doc.getElementsByClassName("svg-container");
var svgNS = g.namespaceURI;
var printLandscape = document.createElementNS(svgNS, "svg");
var useElem = document.createElementNS(svgNS, 'use');
printLandscape.setAttributeNS(svgNS,"class", "print landscape")
printLandscape.setAttributeNS(svgNS, "viewBox", " 800 500 1000 700");
useElem.setAttributeNS(svgNS, 'xlink:href', '#graphic');
printLandscape.appendChild(useElem);
f[0].appendChild(printLandscape);
for (var i=0; i<18; i++){
for (var j=0; j<12; j++) {
r = doc.createElementNS(svgNS, "rect");
r.setAttribute("width", "80");
r.setAttribute("height", "80");
r.setAttribute("x", (i*100 + 10));
r.setAttribute("y", (j*100 + 10));
r.style.setProperty("fill-opacity", ((i*j + 1)%20)/20, null);
g.insertBefore(r, null);
}
}
</script>
<body>
</body>
</head>
</html>



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


xlink:href находится в пространстве имен xlink, а не в пространстве имен svg. На самом деле использование пространства имен не рекомендуется, и практически все браузеры понимают атрибут href без пространства имен. Просто напишите
useElem.setAttribute('href', '#graphic');
Я не понимаю, почему обзорная комиссия продолжает приставать к владельцу вопроса. Как видите, люди могут читать, понимать и отвечать на вопрос спокойно, спокойно и, что более важно. с пользой.