使用动画效果改变文字宽度

16

我有一句话,想在其中一个单词消失之后用数组中的另一个单词替换它并进行渐变。但是,由于单词长度不同,句子宽度会突然改变,导致过渡不流畅。
我该如何动画化宽度的变化?我尝试在CSS中为句子的容器添加转换,但没有效果。我将转换应用为 1.5s all linear,因此每当发生更改时,它都应该动画化宽度以及其他所有内容。有什么想法吗?


$(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>

编辑:如果我表达不清楚,我只想淡化这个单词,而不是整个句子。我试图对宽度进行动画处理以适应新单词。我不想更改/添加任何元素,只是在当前标签中解决问题。


CSS动画不会动画未声明的值...比如从自动宽度到自动宽度...只有当它被设置为精确值时才会动画...比如如果你有100并改变这个值,它将会动画变化。 - Sergei Zahharenko
你可以这样做。通过脚本设置现有单词的宽度。然后在更改之前测量新单词的宽度(有许多不同的方法),并设置其透明度... - Sergei Zahharenko
4个回答

32

Fade animate text with jQuery by Roko C.B.

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>


这个确实可以工作,但是额外的 $ 是什么意思?那是 jQuery 吗?我从未见过变量在名称之前使用 $,这样做的目的是什么? - Josue Espinosa
4
这是一种常用的方式,用于指示该变量是一个指向 HTMLElement 对象的引用。这样做可以使代码更易读。想象一下,如果你有 var width = $('#width'),然后在第 200 行的某个地方读到 width,你可能会认为它是一个数字。使用类似 $width 这样的变量名称可以使代码进一步阅读变得非常清晰明了 - 它肯定是关于一个元素的。 :) - Roko C. Buljan
1
@Limestone 很有趣,只有第一次跟随我的演示链接时出现了问题。其他时间都没有。我已经修改了.show内部回调的调用...应该会有所帮助。 - Roko C. Buljan
@RokoC.Buljan 我得承认当它失效时我没有尝试其他的浏览器或刷新页面,但无论如何现在看起来它正在正常工作。谢谢! - JonathanBristow
@RokoC.Buljan,如果我们想同时动画化两个单词怎么办? - Pawel Gumiela
显示剩余4条评论

2

当您为句子设置新单词时,可以保存#what宽度,并使用此宽度进行动画。像这样:

// 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(){
        });

1

我曾经遇到过同样的问题,但采取了不同的方法,不是淡入淡出而是打字效果: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)
    }
}

基本上,它会将您的新文本插入到页面上,带有漂亮的光标和错别字,使其看起来像是有人正在输入。

这可能更适合于一个“打字机”问题,比如https://dev59.com/x2Yr5IYBdhLWcg3w495- :) - Roko C. Buljan
你说得没错,但这也是一个很好的用于改变句子中文本的动画效果,不过或许应该加快一下速度,同时避免错别字和插入符号。 - Willem

0

试一下:- http://jsfiddle.net/adiioo7/c8fFU/13/

您可以根据需要更新句子效果。目前它正在使用淡入/淡出。

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);

});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接