HummusJS icon indicating copy to clipboard operation
HummusJS copied to clipboard

drawText inside a rectangle with word wrap like word-wrap: break-word in CSS

Open mttrung opened this issue 6 years ago • 3 comments

Hello,

I'm trying to draw a text and restrict it inside a given rectangle (with width, height, x, y). Is there any option for doing something like this?

My idea is using your built-in text measurement to calculate the width of a word and draw a new line when it reaches the border-right of the rectangle. Keep doing this, word by word, until end of the given text. For each new line, I also check if it reaches the border-bottom of the rectangle.

It is quite complicated so I wonder if there is an option for this or any advice to word wrap the text.

Thank you for your help.

mttrung avatar Oct 31 '17 10:10 mttrung

You might be able to find some inspiration in this code: https://github.com/galkahana/hummusrenderrer

galkahana avatar Oct 31 '17 12:10 galkahana

You may take look on the following codes as references too. https://github.com/chunyenHuang/hummusRecipe/blob/master/lib/text.js#L34

chunyenHuang avatar Oct 31 '17 19:10 chunyenHuang

Here's a basic text wrap code. You can get fancier with how you split etc but should be clear enough.


const writeTextWrap = (pdfWriter, text, params, options = {}) => {
 

  // textOptions, pageModifer and context you would already have but here for clarity
  const textOptions = {
    font: pdfWriter.getFontForFile(resolve('./arial.ttf')),
    size: 12,
    colorSpace: 'rgb',
    color: 0xDC143C
  }
  const page = 0
  const pageModifier = new hummus.PDFPageModifier(pdfWriter, page)
  const context = pageModifier.startContext().getContext()

  // Begin text wrap code

  // Break text into words, keeping punctuation w previous word.
  const elements = text.split(/\s/)

  // Build array w text and width
  let words = elements.map(e => {
    return {
      width: textOptions.font.calculateTextDimensions(e, textOptions.size).width,
      text: e
    }
  })

  // Set max widfth of text box, and x,y top left coordinates as well as line height and space width
  const x = 20
  const y = 20
  const width = 500
  const line = 10
  const space = 5

  // Keep track of current line width
  let dimension = 0
  let xPos = x
  let yPos = y

  // Loop through each word
  for (let w of words) {
    // Check if it would go beyond bounds - if so add a line and reset width
    if (dimension + w.width > width) {
      dimension = 0
      yPos -= line
    }

    // Write line as normal
    context.writeText(
      w.text,
      dimension + xPos,
      yPos,
      textOptions)

    // Update line width w space
    dimension += w.width + space
  }
}

cyberwombat avatar Jun 14 '19 17:06 cyberwombat