首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >JsPDF粗体、法线和对齐行

JsPDF粗体、法线和对齐行
EN

Stack Overflow用户
提问于 2022-04-26 13:00:30
回答 1查看 494关注 0票数 1

我使用JsPdf从API响应创建我的pdf。我还在同一行中实现了大胆和正常的词。此逻辑是从下面的链接复制的。现在我想让这篇文章成为“正当的”。我怎么能这么做。下面是引用的快照,

https://codepen.io/AndreKelling/pen/BaoLWao

下面突出显示中间有粗体字,所以我无法在文本上应用这个理由。但是其他没有粗体字的段落是正确的。

如何使用粗体和普通文本混合,以及文本样式对齐和自定义字体。我要用jspdf做这个?任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

发布于 2022-08-12 20:14:52

我已经基于您共享的代码页进行了修改,使文本在多行格式下是合理的,请检查下面的代码。

https://codepen.io/cat_developer/pen/mdxGYvM

代码语言:javascript
运行
复制
// setup config
const fontSize = 13;
const lineSpacing = 12;

// ><><><><><><><<><><<><
// MULTILINE EVENT
// ><><><><><><><<><><<><
document.getElementById("printMultiline2").addEventListener("click", function(){
  let startX = 12;
  let startY = 20;
  const doc = new jsPDF("p", "pt");
  doc.setFont("arial")
    .setFontSize(fontSize)
    .setFontStyle("normal");
  
  let inputValue = document.getElementById("multiline2").value;  
  const endX = 360;
  // red marks to make textwidth visible
  doc.setDrawColor('#ff0000');
  doc.setLineWidth(1);
  doc.line(startX, startY - 10, startX, startY + 200);
  doc.line(endX+startX, startY - 10, endX+startX, startY + 200); 
  
 printCharacters(doc, inputValue, startY, startX, endX);
  
  doc.save(`boldAndNormal-multiline2.pdf`);
});

const getTextRows = (doc, inputValue, width) => {
    const regex = /(\*{2})+/g; // all "**" words
    const textWithoutBoldMarks = inputValue.replace(regex, '');  
    const boldStr = 'bold';
    const normalStr = 'normal';
    const fontSize = doc.getFontSize();

    let splitTextWithoutBoldMarks = doc.splitTextToSize(
        textWithoutBoldMarks,
        360
    );

    let charsMapLength = 0;
    let position = 0;
    let isBold = false;

    // <><>><><>><>><><><><><>>><><<><><><><>
    // power algorithm to determine which char is bold
    let textRows = splitTextWithoutBoldMarks.map((row, i) => {
        const charsMap = row.split('');

        const chars = charsMap.map((char, j) => {
           position = charsMapLength + j + i;

           let currentChar = inputValue.charAt(position);

           if (currentChar === "*") {
              const spyNextChar = inputValue.charAt(position + 1);
              if (spyNextChar === "*") {
                 // double asterix marker exist on these position's so we toggle the bold state
                 isBold = !isBold;
                 currentChar = inputValue.charAt(position + 2);

                  // now we remove the markers, so loop jumps to the next real printable char
                  let removeMarks = inputValue.split('');
                  removeMarks.splice(position, 2);
                  inputValue = removeMarks.join('');
                }
           }

           return { char: currentChar, bold: isBold };
        });
        charsMapLength += charsMap.length;

        // Calculate the size of the white space to justify the text
        let charsWihoutsSpacing = Object.entries(chars).filter(([key, value]) => value.char != ' ');
        let widthRow = 0;

        charsWihoutsSpacing.forEach(([key, value]) => {
            // Keep in mind that the calculations are affected if the letter is in bold or normal
            doc.setFont(undefined, value.bold ? boldStr : normalStr);
            widthRow += doc.getStringUnitWidth(value.char) * fontSize;
        });

        let totalBlankSpaces = charsMap.length - charsWihoutsSpacing.length;
        let blankSpacing = (width - widthRow) / totalBlankSpaces;

        return {blankSpacing: blankSpacing, chars: { ...chars }};
    });
  
    return textRows;
}

const printCharacters = (doc, text, startY, startX, width) => {
    const startXCached = startX;
    const boldStr = 'bold';
    const normalStr = 'normal';
    const fontSize = doc.getFontSize();
    const lineSpacing = doc.getLineHeightFactor() + fontSize;
  
    let textObject = getTextRows(doc, text, width);

    textObject.map((row, rowPosition) => {

        Object.entries(row.chars).map(([key, value]) => {
            doc.setFontType(value.bold ? boldStr : normalStr);
            doc.text(value.char, startX, startY);
          
            if(value.char == ' ' && rowPosition < textObject.length - 1){
                startX += row.blankSpacing;
            } else {
                startX += doc.getStringUnitWidth(value.char) * fontSize;
            }
        });
        startX = startXCached;
        startY += lineSpacing;
    });
};
代码语言:javascript
运行
复制
// just styling, no essential functionality here...
body {
  font-family: sans-serif;
}

input,
textarea {
  width: 33rem;
}

textarea {
  height: 11rem;
}

i {
  display: block
}

header {
  padding: 1rem;
  background: #efefef;
}

section {
  padding: 1rem 1rem 2rem;
}
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<header>
  <h1>jspdf - mixed normal and bold font</h1>
  <a href="https://codepen.io/AndreKelling/pen/BaoLWao" target="_blank">Source <strong>AndreKelling</strong></a>
  <h2>with the help of double asterix markers</h2>
  <i>somehow printing multiple times adds more text. shouldnt happen normally</i>
</header>

<section style="background:#999">
  <h3>for mutli-line text</h3>
  <i>now whole bold text-lines can get printed over borders</i>
  <textarea id="multiline2">this shall be the multi-line text with **bold words** and normal font mixed up. this will need some **more text with** slightly different cases inside.
**when** there **are** lots **of** bold **markers** the **text** shrinks **in** that **line**. yes because of splitTextToSize calculates the markers in. **which is fixed with this technique. but whole bold lines will get slightly over the borders of the pritnable area.** because bold font is normally wider than normal weighted text.</textarea>
<button id="printMultiline2">generate PDF</button>
</section>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72014417

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档