Is there an easy way to bold individual words while using text()?

I want to print

My name is Bassam.

on the canvas.

This is the code I had to write:

function setup() {
  const x = 50,
    y = 100;
  let xpos;
  createCanvas(400, 400);
  background("white");
  textSize(28);

  text("My", x, y);
  xpos = textWidth("My");
  textStyle(BOLD);
  text(" name", x + xpos, y);
  xpos = xpos + textWidth(" name");
  textStyle(NORMAL);
  text(" is Bassam.", x + xpos, y);
}

Link

Is there an easier way to do this?

Thanks!

interested …

this in java mode

String  t_str;

void setup() {
  fullScreen();
 
  textAlign(CENTER);
  textSize(70);
  t_str = "add your text";
  textSize(12); // To create a "text width factor",
  float twf = width/textWidth(t_str);
  int f = 4; // Empericaly found 
  textSize(f*twf); // Making it  proportional for other screen resolutions
text(t_str, width/2, height/2);
}
1 Like
3 Likes

Hi,

Interesting question! :wink:

Ideally the most flexible way to do this is to use HTML and CSS to style your text since it’s more powerful and it was made for that.

Now if you want to do this in p5js using only the text() and textStyle(BOLD) functions, you can get inspiration from the Markdown syntax :

I just love **bold text**. → I just love bold text .

So using two asterisks between some portion of text indicate that we want this to be bold.

What if we could have a function to do that automatically for us?

This is my take on this :

function splitByBold(text) {
  const result = [];
	
  let previousIndex = 0;
  
  // Indicate wether we are currently in a bold text
  let isCurrentBold = false;
	
  // Go through every character
  for (let i = 0; i < text.length; i++) {
    // True if there's two asterisks from the current index
    const isTwoAsterisks = (text[i] == '*') && (i < text.length - 1) && (text[i + 1] == '*');
    
    // True if we are at the end (useful to get the last letter)
    const isLastIndex = i == text.length - 1;

    // We detected two asterisks
    if (isTwoAsterisks || isLastIndex) {
      
      // The last index to take
      const lastIndex = isLastIndex ? i + 1 : i;
			
      // Add that piece of text
      result.push({
        text: text.slice(previousIndex, lastIndex),
        bold: isCurrentBold
      });
			
      // The previous index becomes the new one, add 2 if two asterisks
      previousIndex = isTwoAsterisks ? i + 2 : i;
      
      // Invert the current state
      isCurrentBold = !isCurrentBold;
    }
  }

  return result;
}

Here are the results :

console.log(splitByBold("My **name** is Bassam."));

// 0: Object { text: "My ", bold: false }
// 1: Object { text: "name", bold: true }
// 2: Object { text: " is Bassam.", bold: false }
// length: 3

console.log(splitByBold("This is **bold even **inside** yeah!**."));

// 0: Object { text: "This is ", bold: false }
// 1: Object { text: "bold even ", bold: true }
// 2: Object { text: "inside", bold: false }
// 3: Object { text: " yeah!", bold: true }
// 4: Object { text: ".", bold: false }
// length: 5

Now you can take the result of this function to make the drawing part, it shouldn’t be too hard :slight_smile:

2 Likes

I was curious about this too. Expanding on @josephh 's css idea I made a paragraph overlay on the canvas

https://editor.p5js.org/micuat/sketches/JqrmYejJm

upside is basically you can do everything you want with html/css but downside is you cannot edit pixels of the text or overlay contents on the text (unless you make another transparent canvas on top of the paragraph)

3 Likes

Very useful all. Thanks.

My use case is quite unique and I think I need to bold only 1 word on a page so I think doing it the hard way might be the best option for me.

And you speak the truth @micuat :slight_smile: