动画修改/更改文本时移动的HTML对象

时间:2018-03-26 17:10:20

标签: javascript jquery html css css-animations

我有这段代码:



<span><img id="user" src="http://placehold.it/100x100" alt="img"></span>
<span><h2 id="textToChange">text here</h2></span>
&#13;
&#13;
&#13;

当我更改#textToChange时,#user会自动移动,因为文本会发生变化,因为它会移动它。我想动画#user,这样它将以线性动画移动,而不是仅仅到达x值。 有可能实现或我疯了吗?感谢。

1 个答案:

答案 0 :(得分:1)

这是一个有趣的小问题。让我把它分解成几个步骤:

  1. 查找图片的当前位置
  2. 找到需要迁移的地方
  3. 移动
  4. 更改文字
  5. 现在,困难的部分是第2步和第3步。

    对于第2步,您必须计算新文本的长度。这很棘手,因为没有内置函数可以告诉您文本与给定样式集的宽度。你几乎必须创建一个重复的元素并测量它。

    对于步骤3,您必须在文本更改之前或之后移动元素而不会导致跳转。我这样做的方法是使用position: absolute并将left设置为当前位置(从而消除那里的任何混乱)。然后,我使用transform(为了当前位置做一些数学计算)转换到正确的位置,以获得性能。在转换结束时,请删除style属性并更改文本。

    需要注意的另一件事是当图像变为position: absolute时文本会四处跳跃。为简单起见,我将整行放在display: flex容器中。如果您不想使用flex,可以在文本上使用inline-blockblock并调整填充/高度,以便保留适当的空间。

    这是我想出的(也在JSFiddle上):

    var $img = document.getElementById('user');
    var $text = document.getElementById('textToChange');
    var $estimator = document.getElementById('estimator');
    
    var extraWidth = $img.offsetLeft - $text.offsetWidth;
    
    function estimate(text) {
      $estimator.textContent = text;
    
      var width = $estimator.offsetWidth;
    
      $estimator.textContent = '';
    
      return width;
    }
    
    document.getElementById('change-text')
      .addEventListener('click', function() {
        var newText = randomText();
    
        var left = $img.offsetLeft;
    
        $img.style.position = 'absolute';
        $img.style.left = left + 'px';
        $img.style.transition = 'transform linear 1s';
        $img.style.transform = 'translateX(0)';
    
        window.requestAnimationFrame(function() {
          $img.style.transform = 'translateX(' + (extraWidth + estimate(newText) - left) + 'px)';
    
          window.setTimeout(function() {
            $text.textContent = newText;
            $img.removeAttribute('style');
          }, 1000);
        });
      });
    
    // For testing
    function randomText() {
      var length = Math.floor(Math.random() * 43) + 3;
    
      return 'Lorem ipsum dolor sit amet portris noc tefweep'.slice(0, length);
    }
    h2 {
      position: relative;
      height: 100px;
      display: flex;
      align-items: flex-end;
    }
    
    /* For measuring text width. I don't want it to be seen. */
    .not-shown {
      visibility: hidden;
      color: transparent;
      position: absolute;
      z-index: -1;
    }
    <h2>
      <span id="textToChange">text here</span>
      <img id="user" src="http://placehold.it/100x100" alt="img">
    </h2>
    
    <h2 class="not-shown"><span id="estimator"></span></h2>
    
    <button id="change-text">Change text</button>

    请注意,如果文本转到多行,这不会很好。我选择不担心这种情况。