Animated text / Spacing problem


#1

Hi Everyone,

I am trying to create an animated text, starting with a random size and color on the page.
Each letter move according a sine fonction.

Unfortunately, i get lost in my thoughts and don’t understand anymore why i don’t have the result that i am expected.

The text start with right random sizes but wrong spacing and when i am starting to make the letters move, i am losing the random effect and spacing still a problem.

Can someone help me please?

Thank you,

Rémy

PFont f;
String message = "WEIRD";
Letter[] letters;

void setup(){
  size (400,200);
  f = createFont ("Arial",40,true);
  textFont(f);
  
  letters = new Letter[message.length()];
  int x = 100;
  
  for (int i = 0; i < letters.length; i++){
    letters[i] = new Letter (x, height/2,message.charAt(i));
    x += textWidth (message.charAt(i));   
  }
}

void draw(){
  background(0);
  
  for (int i = 0; i < letters.length; i++){
    letters[i].display();
    letters[i].grow();
  }
}

class Letter{
  float x,y;
  char letters;
  
  float s;
  float c;
  float g;
  
  Letter( float _x, float _y, char _letters){
    x = _x;
    y = _y;
    letters = _letters;
    s = random(20,80);
    c = random(50,200);
    g = 0;   
  }

  void display(){
    fill(c);
    textAlign(LEFT);
    textSize(s);
    text(letters,x,y);
  }
  
  void grow(){
    s = map (sin(g),-1,1,5,100);
    g += 0.05;
  }
}

#2
PFont f;
String message = "WEIRD";
Letter[] letters;

void setup() {
  size (400, 200);
  f = createFont ("Arial", 40, true);
  textFont(f);
  letters = new Letter[message.length()];
  int x = 100;
  for (int i = 0; i < letters.length; i++) {
    letters[i] = new Letter (x, height/2, message.charAt(i));
    x += textWidth (message.charAt(i));
  }
}

void draw() {
  background(0);
  for (int i = 0; i < letters.length; i++) {
    letters[i].grow();
    letters[i].display();
  }
}

class Letter {
  float x, y;
  char letters;

  float s;
  float c;
  float g;

  Letter( float _x, float _y, char _letters) {
    x = _x;
    y = _y;
    letters = _letters;
    s = random(20, 80);
    c = random(50, 200);
    g = random(TWO_PI);
  }

  void display() {
    fill(c);
    textAlign(LEFT);
    textSize(s);
    text(letters, x, y);
  }

  void grow() {
    g += 0.05;
    g %= TWO_PI;
    s = map( sin(g), -1, 1, 12, 100 );
  }
}

I have fixed the random sizes issue. Before, each letter’s size, s, may have started at random, but was immediately changed to be based on g… which wasn’t random!

I have no idea how you want the letters spaced, so I am unable to help with that. Should the letters never overlap? Should they be spaced out more equally? You weren’t clear. Perhaps a mock-up image or two would help us?


#3

Hi @TfGuy44

Thank you for your answer. I didn’t saw that i had g=0; in my settings :sweat:

Regarding the spacing between the letters, i want to have a typographical justification on the left corner (see red dots line on mock-up). When the letters change their sizes, the spacing is conserved regarding their width. Does it makes sens to you?

Let me know.

Best,

Rémy


#4

You are storing absolute coordinates (x, y) in your Letter class - but there is no way for each letter to know its cumulative offset without giving it a way to check the list of all the letters to the left of it. Its absolute position shouldn’t be its job.

Instead, you want a cursor variable or class. Each time a letter is printed, it knows its own width (because the textSize is set) – at that moment, it needs to tell the cursor how wide it is, and the cursor will advance by that much. Then print the next letter, etc.

// https://discourse.processing.org/t/animated-text-spacing-problem/4559/4
// 2018-10-25

PFont f;
String message = "WEIRD";
Cursor cursor;
Letter[] letters;

void setup() {
  size (400, 200);
  // font
  f = createFont ("Arial", 40, true);
  textFont(f);
  textAlign(LEFT);
  // message
  letters = new Letter[message.length()];
  for (int i = 0; i < letters.length; i++) {
    letters[i] = new Letter (message.charAt(i));
  }
  //cursor -- really just an x variable that updates
  // by the width of each letter typed.
  cursor = new Cursor();
}

void draw() {
  background(0);
  translate(100, height/2.0);
  for (int i = 0; i < letters.length; i++) {
    // change letter size
    letters[i].grow();
    // type each letter at cursor location
    // -- this advances the cursor by the current letter-width
    cursor.type(letters[i]);
  }
  cursor.x = 0;  // reset cursor
}

class Cursor {
  float x = 0;
  void type(Letter letter) {
    letter.display(x, 0);
    x += letter.width();
  }
}

class Letter {
  float fillColor;
  char letter;
  float scale;
  float scaleStep;

  Letter(char _letter) {
    letter = _letter;
    scale = random(TWO_PI);
    scaleStep = 0.05;
    fillColor = random(50, 200);
  }

  void display(float x, float y) {
    pushStyle();
    fill(fillColor);
    textSize(this.size());
    text(letter, x, y);
    popStyle();
  }

  float grow() {
    return scale += scaleStep;
  }

  float size() {
    return map(sin(scale), -1, 1, 12, 100);
  }

  float width() {
    pushStyle();
    textSize(this.size());
    float letterWidth = textWidth(letter);
    popStyle();
    return letterWidth;
  }
}

PulsingLetterCursor--screenshot


Self rendering objects?
#5

Hi @jeremydouglass

Sorry for my late answer, i didn’t see yours.
This is exactly what i was looking for. Your cursor solution is a smart approach.

Thank you for the helping hand :wave:

Best,

Rémy