如何动态平铺 svg 打印输出
How to tile svg print output dynamically
我有很大的 svg 图纸,开头的尺寸未知。我想将它们打印在多页上;但最初不知道页数。所以我必须在确定图纸尺寸并相应地添加 svg 元素后决定 Javascript 内的页数。
https://codepen.io/anon/pen/roYXVJ 中有一个很好的示例,它是 "static" 平铺,即页面的大小和数量是预先固定的。代码的简化版本(没有箭头和索引字母)如下所示:
<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 的属性,因为它被 "use" 函数使用(?)。因此,应定义另一个 use 元素以指向 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>
xlink:href
在 xlink 命名空间中,而不是 svg 命名空间中。实际上,命名空间的使用已被弃用,几乎所有浏览器都理解没有命名空间的 href
属性。简单写
useElem.setAttribute('href', '#graphic');
我有很大的 svg 图纸,开头的尺寸未知。我想将它们打印在多页上;但最初不知道页数。所以我必须在确定图纸尺寸并相应地添加 svg 元素后决定 Javascript 内的页数。
https://codepen.io/anon/pen/roYXVJ 中有一个很好的示例,它是 "static" 平铺,即页面的大小和数量是预先固定的。代码的简化版本(没有箭头和索引字母)如下所示:
<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 的属性,因为它被 "use" 函数使用(?)。因此,应定义另一个 use 元素以指向 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>
xlink:href
在 xlink 命名空间中,而不是 svg 命名空间中。实际上,命名空间的使用已被弃用,几乎所有浏览器都理解没有命名空间的 href
属性。简单写
useElem.setAttribute('href', '#graphic');