JSPDF大胆,正常和正当

发布于 2025-01-24 06:25:06 字数 431 浏览 1 评论 0原文

我正在使用JSPDF从API响应中创建我的PDF。我还以同一行实现了大胆和普通的单词。此逻辑从下面的链接复制。现在,我想将文本“正当”做。我该怎么做。以下是参考的快照,

[https://codepen.io/andrekelling/pen/baolwao] [1]

下面突出显示了两者之间的大胆单词,因此我无法将其正当应用于文本。但是其他没有任何粗体字的段落是正确的。

我如何使用粗体和普通文本混合以及文本样式合理和自定义字体。我是 为此使用JSPDF?任何帮助将不胜感激。

I am using JsPdf to create my pdf from the API response. I have also implemented the bold and normal word in same line. This logic is copied from below link. Now I want to make the text "justify". How can I do that. Below is the snapshot for the reference,

[https://codepen.io/AndreKelling/pen/BaoLWao][1]

The below highlighted having bold word in between, so I am not able apply the justify on the text. But other paragraph which do not have any bold word is correctly justify.
https://i.sstatic.net/n4Nm8.png

How Can I use both bold and normal text mix along with text style justify and custom font. I am
using jspdf for this? Any help would be highly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

究竟谁懂我的在乎 2025-01-31 06:25:06

我基于您共享的代码蛋白,并进行了修改,以便以多行格式为文本是合理的,请检查下面的代码。

https://codepen.io/cat_io/cat_developer/pen/pen/pen/mdxgym

// 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;
    });
};
// 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;
}
<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>

i have based on the codepen that you shared, and I have made the modifications so that the text is justified in the multiline format, please check the code below.

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

// 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;
    });
};
// 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;
}
<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>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文