我的内容很长(包含图片,列表,div,文本等的多个内容)。我想将此内容显示为虚拟PDF页面。我不想生成PDF,只需将此HTML内容显示为具有相同页眉/页脚的页面(由宽度/高度定义)即可。它的外观如下图所示,就像您在首页上看到的那样,我想拆分该文本并在下一页中显示:
我正在React上使用此应用程序。我不知道该内容将是什么,每个渲染都将有所不同(根据用户活动,其内容将有所不同)。
您对此有何建议? (CSS解决方案或JS,或者我不知道可能有一些React lib ...)
答案 0 :(得分:2)
这是一个幼稚但可行的实现。
想法是将html挂载到屏幕外的div中,该div的尺寸与我们尝试呈现的页面的尺寸相同。
然后遍历此屏幕外div的元素(即,来自解析的html的children),并使用getBoundingClientRect查询dom,以查找第一个溢出元素。
然后,我们将所有元素从屏幕div上移除,然后将其缓存在数组中。
重新开始一个新的块,直到屏幕外的div中不再有任何元素。
使其适应于React只需在每个页面的html内容中使用dangerouslySetInnerHTML。
(显示柔韧性仅用于强制元素流动,但是只要在offscreenDiv和页面中相同,任何布局都可以做到)
function generateRandomContent() {
var alph = "abcdefghijklmnopqrstuvwxyz";
var content = "";
// we will generate 100 random elements displaying their index to keep track of what's happening
for (var i = 0; i < 100; i++) {
var type = parseInt(Math.random() * 2, 10);
switch (type) {
case 0: // text, generates and random p block
content = content + "<p>" + i + " ";
var numWords = 10 + parseInt(Math.random() * 50, 10);
for (var j = 0; j < numWords; j++) {
var numLetters = 2 + parseInt(Math.random() * 15, 10);
if (j > 0) {
content = content + " ";
}
for (var k = 0; k < numLetters; k++) {
content = content + alph[parseInt(Math.random() * 26, 10)];
}
}
content = content + "</p>";
break;
case 1: // colored div, generates a div of random size and color
var width = 30 + parseInt(Math.random() * 20, 10) * 10;
var height = 30 + parseInt(Math.random() * 20, 10) * 10;
var color = "rgb(" + parseInt(Math.random() * 255, 10) + ", " + parseInt(Math.random() * 255, 10) + ", " + parseInt(Math.random() * 255, 10) + ")";
content = content + '<div style="width: ' + width + 'px; height: ' + height + 'px; background-color: ' + color + '">' + i + '</div>';
break;
}
}
return content;
}
function getNodeChunks(htmlDocument) {
var offscreenDiv = document.createElement('div');
offscreenDiv.className = 'page';
offscreenDiv.style.position = 'absolute';
offscreenDiv.style.top = '-3000px';
offscreenDiv.innerHTML = htmlDocument;
offscreenDiv.display = 'flex';
offscreenDiv.flexWrap = 'wrap';
document.body.appendChild(offscreenDiv);
offscreenRect = offscreenDiv.getBoundingClientRect();
// console.log('offscreenRect:', offscreenRect);
var chunks = [];
var currentChunk = []
for (var i = 0; i < offscreenDiv.children.length; i++) {
var current = offscreenDiv.children[i];
var currentRect = current.getBoundingClientRect();
currentChunk.push(current);
if (currentRect.bottom > (offscreenRect.bottom)) {
// current element is overflowing offscreenDiv, remove it from current chunk
currentChunk.pop();
// remove all elements in currentChunk from offscreenDiv
currentChunk.forEach(elem => elem.remove());
// since children were removed from offscreenDiv, adjust i to start back at current eleme on next iteration
i -= currentChunk.length;
// push current completed chunk to the resulting chunklist
chunks.push(currentChunk);
// initialise new current chunk
currentChunk = [current];
offscreenRect = offscreenDiv.getBoundingClientRect();
}
}
// currentChunk may not be empty but we need the last elements
if (currentChunk.length > 0) {
currentChunk.forEach(elem => elem.remove());
chunks.push(currentChunk);
}
// offscreenDiv is not needed anymore
offscreenDiv.remove();
return chunks;
}
function appendChunksToPages(chunks) {
var container = document.getElementsByClassName('root_container')[0];
chunks.forEach((chunk, index) => {
// ex of a page header
var header = document.createElement('div');
header.innerHTML = '<h4 style="margin: 5px">Page ' + (index + 1) + '</h4>';
container.appendChild(header);
var page = document.createElement('div');
page.className = 'page';
chunk.forEach(elem => page.appendChild(elem));
container.appendChild(page);
});
}
// generateRandom content outputs raw html, getNodeChunks returns
// an array of array of elements, the first dimension is the set of
// pages, the second dimension is the set of elements in each page
// finally appendChunks to pages generates a page for each chunk
// and adds this page to the root container
appendChunksToPages(getNodeChunks(generateRandomContent()));
.page {
border: 1px solid;
display: flex;
flex-wrap: wrap;
height: 700px;
width: 50%;
margin-bottom: 20px;
}
<div class="root_container"></div>