Animate changing words width

2019-01-10 18:17发布

问题:

I have a sentence in which one word fades out, and is replaced by another word in an array. However, since the words all vary in length, the sentence width abruptly changes and it looks choppy.
How can I animate the width? I tried adding a transition to the container of the sentence in css but that didn't work. I applied the transition as 1.5s all linear, so it should be animating the width as well as everything else whenever there is change. Any ideas?

$(function() {
  var hello = ['dynamic', 'a', 'aklsjdlfajklsdlkf', 'asdf'];
  var used = ['dynamic'];
  var greeting = $('#what');
  var item;

  function hey() {

    item = hello[Math.floor(Math.random() * hello.length)];
    if (hello.length != used.length) {
      while (jQuery.inArray(item, used) != -1) {
        item = hello[Math.floor(Math.random() * hello.length)];
      }
      used.push(item);
    } else {
      used.length = 0;
      item = hello[Math.floor(Math.random() * hello.length)];
      used.push(item);
    }
    greeting.html(item);
    greeting.animate({
      "opacity": "1"
    }, 1500);
  }

  window.setInterval(function() {
    greeting.animate({
      "opacity": "0"
    }, 1500);
    setTimeout(hey, 1500)
  }, 5000);

});
#sentence {
  transition: 1.5s all linear;
}

#what {
  font-style: italic;
  text-decoration: underline;
  color: red;
}
<p id="sentence">
  This is a sentence that has <span id="what">dynamic</span> text that alters width.
</p>

<script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

EDIT: Sorry if I was unclear, I only want to fade out the word, not the entire sentence. I'm trying to animate the width to fit the new word. I don't want to change/add any elements, just solve with the current tags in place.

回答1:

function dataWord () {

  $("[data-words]").attr("data-words", function(i, d){
    var $self  = $(this),
        $words = d.split("|"),
        tot    = $words.length,
        c      = 0; 

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

    // COLLECT WORDS AND HIDE
    $words = $self.find("span").hide();

    // ANIMATE AND LOOP
    (function loop(){
      $self.animate({ width: $words.eq( c ).width() });
      $words.stop().fadeOut().eq(c).fadeIn().delay(1000).show(0, loop);
      c = ++c % tot;
    }());
    
  });

}

// dataWord(); // If you don't use external fonts use this on DOM ready; otherwise use:
$(window).on("load", dataWord);
p{text-align: center;font-family: 'Open Sans Condensed', sans-serif;font-size: 2em;}

/* WORDS SWAP */
[data-words]{
  vertical-align: top;
  position: static;
}
[data-words] > span{
  position: absolute;
  color: chocolate;
}
<link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300' rel='stylesheet' type='text/css'>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>
  We provide
  <span data-words="code|solutions|design"></span>
  for your business.
</p>

<p>
  You ordered
  <span data-words="1|3|28"></span>
  <b>big</b>
  <span data-words="salad|macs|chips"></span>
</p>



回答2:

When you set new word for your sentence, you can save #what width and then make an animation with this width too. Like this:

// declare as global variable and update when you set new word
var width = greeting.css('width'); 
// animation
greeting.animate({
            "opacity": "0", "width": width
        }, 1500, function(){
        });


回答3:

Try this out:- http://jsfiddle.net/adiioo7/c8fFU/13/

You can update the sentence effect depending upon your requirement. Currently it is using fadein/fadeout.

JS:-

$(function () {
    var hello = ['jupiter', 'a', 'aklsjdlfajklsdlkf', 'asdf'];
    var used = ['jupiter'];
    var greeting = $('#what');
    var item;
    var sentence = $('#sentence');

    function hey() {
        item = hello[Math.floor(Math.random() * hello.length)];
        if (hello.length != used.length) {
            while (jQuery.inArray(item, used) != -1) {
                item = hello[Math.floor(Math.random() * hello.length)];
            }
            used.push(item);
        } else {
            used.length = 0;
            item = hello[Math.floor(Math.random() * hello.length)];
            used.push(item);
        }
        greeting.html(item);
        greeting.animate({
            "opacity": "1"
        }, 1500);

        sentence.fadeIn(1500);
    }

    window.setInterval(function () {
        sentence.fadeOut(1500);
        greeting.animate({
            "opacity": "0"
        }, 1500);
        setTimeout(hey, 1500);
    }, 5000);

});


回答4:

Not to brag but...

Best one you'll see

CSS:

span {
    float: left;
}
#what {
    margin: 0 3px;
}

HTML:

<span class="cf">hello this is a sentence </span><span id="what" class="cf">jupiter</span><span class="cf"> that changes like this:</span>

Javascript:

$(function () {
    var hello = ['jupiter', 'a', 'aklsjdlfajklsdlkf', 'asdf'];
    var used = ['jupiter'];
    var greeting = $('#what');
    var item;

    function hey() {

        item = hello[Math.floor(Math.random() * hello.length)];
        if (hello.length != used.length) {
            while (jQuery.inArray(item, used) != -1) {
                item = hello[Math.floor(Math.random() * hello.length)];
            }
            used.push(item);
        } else {
            used.length = 0;
            item = hello[Math.floor(Math.random() * hello.length)];
            used.push(item);
        }
        greeting.text(item);
        greeting.animate({
            "width": "toggle",
                "opacity": 1
        }, 1500);
    }

    window.setInterval(function () {
        greeting.animate({
            "width": "toggle",
                "opacity": 0
        }, {
            duration: 1500,
            complete: setTimeout(hey, 1500)
        });
    }, 5000);

});


回答5:

I have had the same problem and went with a different approach, not fading but typing: jsfiddle demo

function type($el, text, position) {
    if (text.length >= position) {
        var rchars = 'qbvol'; // typo chars
        if (position % 3 == 0 && Math.random() > .85) { // insert typo!
            var typo;
            var chr = text.substr(position, 1);
            if (chr == chr.toUpperCase()) { typo = chr.toLowerCase(); }
            else { typo = rchars.substr(Math.floor(Math.random() * rchars.length), 1); }
            $el.text(text.substring(0, position - 1) + typo + '_');
            setTimeout(function() { type($el, text, position - 1); }, 200)
        }
        else {
            $el.text(text.substring(0, position) + '_');
            setTimeout(function() { type($el, text, position + 1); }, 150)
        }
    }
    else {
        setTimeout(function() { $el.text(text); }, 400)
    }
}

It basically inserts your new text on the page, with a nice caret and typo to make it look like someone is typing it.