使用 paged.js 控制分页符和分栏符

Ben*_*Ben 8 html javascript css printing css-paged-media

我有一个用于打印的 2 列布局。h2-5 在列内,h1s 跨越两列。我正在使用Paged.js进行分页。

这两个页面显示了可接受的布局:

在此处输入图片说明

但是,如果出现标题位于列底部的情况,我希望将标题强制到下一列的顶部。

在此处输入图片说明

如果一篇新文章从页面底部 40% 开始,我也希望它也被强制转到下一页。

在此处输入图片说明

对于 h2 及以下,我在标题上方注入一个 div,如果标题位于其列的底部,则将其膨胀以推入下一列。

在此处输入图片说明

这似乎对 h2-5 起作用,因为它们位于由浏览器管理的流中。但前提是它们在左栏中;如果他们是对的,他们就会被撞出页面。例如:

在此处输入图片说明

将 H1 从页面上弹出会导致问题,垫片膨胀,但将标题推入一个不可见的区域,或其他一些奇怪的情况。

在此处输入图片说明 在此处输入图片说明

第一张图片显示了出现在第二张图片中的标题,从页面上消失了。

以下(稍微简化的)标记是生成第 11 页(右图,第二张图)的原因

<div class="the-articles">
  <article class="architectural-review.com paper-story noted">
    <p>
      No question, Rem is a genius. Nonetheless, his wake is toxic: stained by
      Randian egos (both triumphal and crushed), the intense interpersonal
      competition, and the exploitation of intellectual and manual labour. How
      does it all end, you wonder. In some ways, Tomas Koolhaas’s documentary
      was a preemptive eulogy. Death is present in every shot, tugging at the
      great man’s sleeve. The film is also suffused by an intense melancholy. It
      is the peculiar sadness of endings: when a family line is extinguished,
      when change erases beauty and meaning, when an entire world order
      disintegrates.
    </p>
    <p>
      Starchitects are still with us, even though their era is over. Koolhaas
      himself called time on it in the mid-2000s. It is no contradiction to
      honour them, while admitting that we must give ourselves permission to
      abandon the figure of the heroic architect, and along with it the Western
      blueprint for greatness that Koolhaas has so relentlessly and obsessively
      perfected.
    </p>
    <div class="tail-meta">
      From:
      <span class="url"
        >https://www.architectural?review.com/essays/reputations/rem?koolhaas?1944/10037224.article</span
      >
    </div>
    <!-- SHIM IS HERE -->
    <div class="shim-between-articles" style="height: 181.944px;"></div>
  </article>
  <article id="2415273718" class="newyorker.com paper-story noted">
    <h1 class="article-title" id="h2415273718">
      Love Is Not a Permanent State of Enthusiasm: An Interview with Esther
      Perel
    </h1>
  </article>
</div>

Run Code Online (Sandbox Code Playgroud)

我在里面做 shim-inflation afterPageLayout,它调用这个函数:

function identifyTooCloseToBottomHeading(
  theHeading,
  pageCutoffPercentage,
  page,
  pageFragment
) {
  try {
    if (theHeading !== null && theHeading !== undefined) {
      const pageBox = page.element.getBoundingClientRect();
      const headingBox = theHeading.getBoundingClientRect();
      const pdelta = pageBox.bottom - headingBox.bottom;
      const botPC = pdelta / pageBox.height; //Gives a % up the page. I.e. 100% is the top
      const cutPC = pageCutoffPercentage[theHeading.tagName.toLowerCase()];
      const oneRem = parseFloat(
        getComputedStyle(document.documentElement).fontSize
      );
      if (botPC < cutPC) {
        console.log("at risk", theHeading);
        if (theHeading.previousElementSibling) {
          AdjustShimSize(oneRem);
        } else {
          const thisArticle = theHeading.parentElement;
          const prevArticle = thisArticle.previousElementSibling;
          const shim = prevArticle.querySelector(".shim-between-articles");
          const topMetaBox = thisArticle
            .querySelector(".top-meta")
            .getBoundingClientRect();
          shim.style.height = `${
            theHeading.getBoundingClientRect().height + topMetaBox.height
          }px`;
        }
      }
    }
  } catch (e) {
    console.log(e, theHeading);
  }

  function AdjustShimSize(oneRem) {
    const shim = theHeading.previousElementSibling;
    // calculate the height that it needs to be
    try {
      const shimBox = shim.getBoundingClientRect();
      const container = shim.closest(".the-articles");
      const containerBox = container.getBoundingClientRect();
      // logShimDetails(theHeading, container, shimBox, nextElBox, containerBox, oneRem);
      shim.style.height = `${containerBox.bottom - shimBox.bottom - oneRem}px`;
      console.log("shimmed", theHeading);
    } catch {
      console.log("trouble with", theHeading);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这似乎应该有效,但它不是很优雅。我怀疑我可以用breaktoken? 有没有正确的方法来做到这一点?


对于 H1,我还尝试在上面的文章中添加一个类,具体取决于将标题移到下一页所需的行数。即一系列css规则:

function identifyTooCloseToBottomHeading(
  theHeading,
  pageCutoffPercentage,
  page,
  pageFragment
) {
  try {
    if (theHeading !== null && theHeading !== undefined) {
      const pageBox = page.element.getBoundingClientRect();
      const headingBox = theHeading.getBoundingClientRect();
      const pdelta = pageBox.bottom - headingBox.bottom;
      const botPC = pdelta / pageBox.height; //Gives a % up the page. I.e. 100% is the top
      const cutPC = pageCutoffPercentage[theHeading.tagName.toLowerCase()];
      const oneRem = parseFloat(
        getComputedStyle(document.documentElement).fontSize
      );
      if (botPC < cutPC) {
        console.log("at risk", theHeading);
        if (theHeading.previousElementSibling) {
          AdjustShimSize(oneRem);
        } else {
          const thisArticle = theHeading.parentElement;
          const prevArticle = thisArticle.previousElementSibling;
          const shim = prevArticle.querySelector(".shim-between-articles");
          const topMetaBox = thisArticle
            .querySelector(".top-meta")
            .getBoundingClientRect();
          shim.style.height = `${
            theHeading.getBoundingClientRect().height + topMetaBox.height
          }px`;
        }
      }
    }
  } catch (e) {
    console.log(e, theHeading);
  }

  function AdjustShimSize(oneRem) {
    const shim = theHeading.previousElementSibling;
    // calculate the height that it needs to be
    try {
      const shimBox = shim.getBoundingClientRect();
      const container = shim.closest(".the-articles");
      const containerBox = container.getBoundingClientRect();
      // logShimDetails(theHeading, container, shimBox, nextElBox, containerBox, oneRem);
      shim.style.height = `${containerBox.bottom - shimBox.bottom - oneRem}px`;
      console.log("shimmed", theHeading);
    } catch {
      console.log("trouble with", theHeading);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在 Paged.js 生命周期的同一点应用该类。它有类似的无益结果。


如果我提前知道哪些标题需要打破,我可以给他们一个break-before: column;break-before: page;规则,但内容不是提前知道的。事后添加这些规则似乎不适用于 paged.js 的生命周期。我怀疑这一个生命周期问题,因为如果我在正确的点/正确的处理程序中执行此操作,将内容从页面上推下应该会导致下一页的回流。

小智 1

您好,为了解决这个问题,我添加了一个新组件,并为其提供了必要的高度来发送新页面/列中的内容,这是我的用例的原始实现:

  const attribute = node?.getAttribute('data-pdf-break-past');
  const pageHeight = 967;
  let maxHeightValueBeforeBreak = pageHeight;
  if (attribute) {
    maxHeightValueBeforeBreak = (pageHeight * +attribute) / 100;
  }
  const distanceToTop = node.getBoundingClientRect()?.top + window.scrollY;

  const contentHeightInPage = distanceToTop % pageHeight;
  const marginToSet = pageHeight - contentHeightInPage;
  if (
    (attribute && contentHeightInPage > maxHeightValueBeforeBreak) ||
    node.className.includes('pdf-break-before')
  ) {
    const newNode = document.createElement('div');
    newNode.style.height = `${marginToSet}px`;

    node.parentNode?.insertBefore(newNode, node);
  }
  
Run Code Online (Sandbox Code Playgroud)

在 Paged.js 解析内容后,我使用了 Dom 操作。

请注意,不使用边距或填充,因为可能会导致库出现问题(发生分页时出现奇怪的行为)。