Jump to content
Search Community

Typewriter effect

gareth test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi,

 

This is an interesting challenge that reveals how useful and flexible the GSAP API is. It also reveals how some techniques can blow up in your face if you don't think of all the ways you need your animation to run / behave. 

 

The meat of this challenge (placing the cursor ahead of the character that was just typed) isn't really related much to GSAP. You just have to use a little JavaScript or jQuery to figure out the position of the current character (left and top) and then the width (to position the cursor along the right edge). This can be achieved by some pretty basic jQuery methods like offset() and width(). However the trick is applying those values to the cursor at the right time.

 

Since you are using a staggerFrom() to drive you typewritter, its possible to use an onStart callback to call a function each time a letter is revealed. In this function you just figure out the position of the target of the tween (current character) and place the cursor to the right of it. 

 

You can see my quick and dirty demo here: http://codepen.io/GreenSock/pen/qEoerY?editors=001 

tl.staggerFrom(chars,0.01, {opacity:0, ease:Power1.easeIn, onStart:placeCursor}, 0.08, "+=0.1", blink);

function placeCursor(){
  var thisLetter = $(this.target) //target of the current tween
  var pos = thisLetter.offset();
  var width = thisLetter.width()
  cursor.css({left:pos.left + width, top:pos.top})
  console.log("start", thisLetter.html(), left, pos.top)
}

This works ok for a one-off type of effect. 

 

However, its pretty poor if you want to reverse the animation. You will notice when the timeline yoyos that the cursor does not move. This is because the onStart callbacks do not fire when timeline is reversed (by design). Another bad thing is that each time a letter is revealed (on every iteration) the DOM is being queried and I'm doing all the offset() calculations (which some could argue could hurt performance).

Open the console to see how often that onStart callback fires. Ouch.

 

Here is a better versionhttp://codepen.io/GreenSock/pen/QwmegN?editors=001that uses a loop to generate the timeline.

 

//loop throug all the chars and make them visible AND set cursor to their right at same time
$chars.each(function(index, element){
  var $element = $(element);
  var offset = $element.offset();
  var width = $element.width()
  tl.set($cursor, {left:offset.left + width,  top:offset.top}, (index +1) * revealInterval)
  tl.set($element, {autoAlpha:1}, (index +1) * revealInterval) 
})

In this version I give each character a class of "char" (using charsClass:"char" in the SplitText vars).

I then use jQuery to loop through each element with class of "char"

For every char I insert 2 set()s into a timeline, one that reveals the character, and one that moves the cursor.

 

The main advantage here is that the animation can be reversed and we do minimal DOM querying and measuring. Once the timeline plays through the first time all the cursor positions are recorded.

 

I initially had the cursor blinking the whole time, but realized that it looked better if the blinking only happened when the typing was not happening. 

I created a blink function that is called and the beginning and end of the timeline to handle this.

Although it may not be immediately apparent this allows the timeline to have variable delay and repeatDelay values.

For instance I can have the timeline wait for 3 seconds before repeating without having to add 3 seconds of blinking cursor animation into the timeline.

Another benefit is that I could add play and pause buttons that toggle the blinking of the cursor appropriately too. 

 

Hopefully this helps.

  • Like 7
Link to comment
Share on other sites

  • 5 months later...

HI,

Nice post I tried as well to achive this effect with GSAP but i wanted an Array of word typed inside a sentence one after the other and cleared each time.

I did not want to use tweenMax to keep the weight as low as possible and trying with SplitText i had wierd results on load.

 

so I tried that with TweenLite, CSSPlugin and TextPlugin. And got completely carried away :)

 

find bellow the codepen link to a little javascript object I built.

 

I used a touch of css keyframe animation for the blinking of the cursor to avoid using "yoyo" which i belive is only avaliable on TweenMax.

also you will need a css clas .old with "display:none" so the cursor will stay next to the last charter

 

it's currently work in progress but you have the following options :

 

el: a dom element //the element you want to contain the typewriter (should be inline or inline-block)

elClass: string  //the class to apply to that element on start (defaut empty)

rotateWords: boolean // if you want a rotating array of words

rotateWordsOptions: object //an object with the settings of the rotating words animation

                                    inside this object:

                                    wordsList: Array // an array of words to type

                                    cycle: boolean // if the animation starts again after the last word is typed Default false

                                    clear: boolean // if you want the words to be cleared each times (selected and deleted) Default: false

                                    clearingDuration: number // duration of the clearing in seconds Default 2    

                                    clear_background: hexa color or css name in quotes //Background Color of the selected text before it gets cleared Default '#000'

                                    clear_color: hexa color or css name in quotes //Color of the selected text before it gets cleared Default '#fff'

                                    original_background: hexa color or css name in quotes //Original background of the text (to reset after clearence) Default 'transparent'

                                    original_color: hexa color or css name in quotes //Original color of the text (to reset after clearence) Default #000

                                    append: boolean // if you want the text to be appended isted of cleared (see the codepen bellow) default: false

                                    pause: boolean // if the animation should stop/pause between each words Default false

word: string // if you are typing a single sentence or word and not using the rotateWords

cursorSign: string //set the currsor to what you want could be a symbol or a special charter Default: "|"

autoPlay: Boolean // if the type animation starts on load (you can trigger it later) Default : true

delay: number //Delay before the word animation starts or between each word rotation. (the cursor sohould blink during that time) Default: 2

duration: number //The duration of the type (for the single word or for each rotating words)

 

 

here is a codepen example

See the Pen doaEOJ?editors=101 by Options-it (@Options-it) on CodePen

 

The first example is set to autoPlay, the two other one are triggered by clicking the buttons.

 

I would love to have some feedback as it's my frist try at something like that

  • Like 2
Link to comment
Share on other sites

Hi, thanks for your replies .

I made a couple of changes including your idea Diaco.

 

so now you can specify a easing function when creating the object.

    var easingPower4 = new gsapTypeIt({
      el: document.getElementById('ContainerEl'),
      word: 'simple example',
      easing: Power4.easeInOut
    });

the easing option is set to Linear.easeNone by default.

you can use any easing function, in my codepen I am loading TweenLite, but you can load Tweenmax or EasePack.

 

I also added a charterPerSecond option this would make all rotating words type at the same speed. or will save you test/calculation when working with dynamic text, long paragraphs and such.

 

With a long text:

     var cpsParagraphe = new gsapTypeIt({
      el: document.getElementById('ContainerEl'),
      word: 'Some long string ...............',
      charterPerSecond: 3
    });

With rotating words that have different length ( still have a little bug to fix with the appended words)

var rotating3 = new gsapTypeIt({
      el: document.getElementById('ContainerEl'),
      rotateWords: true,
      delay: 0,
      charterPerSecond: 3,
      rotateWordsOptions : {
        wordsList : ['can', 'have different length','but are typed at the same speed'],
        cycle: false,
        append: true
      }
      
    });

See the Pen doaEOJ by Options-it (@Options-it) on CodePen

  • Like 3
Link to comment
Share on other sites

  • 3 months later...
  • 7 months later...
  • 1 year later...

hmmm... I've never used SplitText with underlined words. The problem is that SplitText breaks those characters into their own absolutely positioned divs so the spaces aren't there after the split. For an underline effect it sounds like you probably want to include the white-space. A similar question was asked and answered in this thread. Perhaps it could help you.

 

Happy tweening.

:)

 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...