7

I'd like to cycle through an array of words creating a text rotation affect. I have most of it working as expected. Is there any way I can use a css transition on the length of the p element?

When traversing from an object with char.length > 10 to an object with char.length < 5 (for example) the movement isn't smooth and I'd like to ease the movement of the text around the word rather than abruptly jumping backwards (or forwards depending on the length of the word)

HTML:

<p><span id="description-rotate"></span> something built on something else.</p>

SASS:

@-webkit-keyframes rotate-text

    0%
        opacity: 0

    30%
        opacity: 1

    50%
        opacity: 1

    70%
        opacity: 1


    100%
        opacity: 0

p
    font-family: 'Helvetica', sans-serif

.rotate-text
   -webkit-animation: rotate-text 3050ms cubic-bezier(0.645,  0.045, 0.355, 1.000) infinite
    -moz-animation: rotate-text 3050ms cubic-bezier(0.645,  0.045, 0.355, 1.000) infinite
    -o-animation: rotate-text 3050ms cubic-bezier(0.645,  0.045, 0.355, 1.000) infinite
    animation: rotate-text 3050ms cubic-bezier(0.645,  0.045, 0.355, 1.000) infinite

Javascript:

var descriptionArray = ['some text', 'some more text', 'some even longer text'];
var descriptionLength = descriptionArray.length;
var description = $('#description-rotate');

function loop(i) {
     description.text(descriptionArray[i%descriptionLength]);
     setTimeout(function() {
        loop(i+1);
        description.addClass('rotate-text');
    }, 3050); // This duration must match the length of the animation
}

loop(0);

I realize this may be a poor way of explaining my goal, check out the CodePen for a better idea of what I'm trying to create.

Thanks!

See: http://codepen.io/anon/pen/JueGx

Cole Roberts
  • 954
  • 3
  • 15
  • 25
  • Please post your code here so that current and future visitors to SO can bask in all of its indented glory! – Jay Blanchard May 28 '14 at 21:13
  • 1
    @ColeRoberts You want something like this? http://stackoverflow.com/questions/20695877/animate-width-for-only-a-word-in-a-title-in-jquery-css – Roko C. Buljan May 28 '14 at 21:31

2 Answers2

6

A simple example using jQuery
is by storing the desired looping / swapping words into the data-* attribute:

$("[data-words]").attr("data-words", function(i, words) {

    var $self = $(this).text(""),
        words = words.split("|"),
        tot   = words.length,
        c     = 0; 

    for(var i=0; i<tot; i++) $self.append($('<span/>',{text:words[i]}));

    var $words = $self.find("span");

    (function loop(){
      $self.animate({ width: $words.eq( c ).width() });
      $words.stop().fadeOut().eq(c).fadeIn().delay(1000).show(0, loop);
      c = ++c % tot;
    }());
    
});
/* DATA-WORDS Loop/swap words in sentence */
[data-words] {
  vertical-align: top;
  position: static;
}
[data-words] > span {
  display: none;
  position: absolute;
  color: #0bf;
}
<p>
  This is <span data-words="some|an interesting|some longer">some</span> text
</p>

<p>
  Say <span data-words="hi|wow">hi</span> to <span data-words="Javascript|Stack Overflow">mom</span>
</p>


<script src="//code.jquery.com/jquery-3.1.0.js"></script>

  • The | -delimited words will be converted to Array and finally to child <span> elements
  • Such span elements need to be absolutely positioned inside the parent span
  • jQuery will than init a recursive loop, calculate the next word width, and animating it (fade + width)
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • This is a little weird, because the usage of `$("[data-words]").attr()` is using the syntax that *sets* the data-words attribute. So by doing this you are actually mutating the value of the data-words attributes which could have weird side effects if you try using it later. You should just be accessing the value, not running a callback to modify it. If it's meant to be looping over each one, it should use `.each()` instead. – nzifnab Oct 31 '19 at 20:40
0

How about jQuery's animate() function? http://api.jquery.com/animate/

You can trigger an animation for each word in the array. Here's an idea, you will have to figure out how populate the variables hasMoreWordsInTheArray and nextWordInTheArray:

function animateParagraphTag(word) {
    if(hasMoreWordsInTheArray) {
        //some special code to calculate the best width based on the word's length (theNewWidthValue)
        $('p').animate(
            { width: theNewWidthValue },
            "fast",
            animateParagraphTag(nextWordInTheArray)
        );
    }
}

You will have to calculate the width based on the length of the words and place that within the parameters of the animation, then, once the p tag finishes the expansion/contraction accordingly, it will trigger the callback function, you can then move on to the next element (word) of the array.

the_marcelo_r
  • 1,847
  • 22
  • 35