【问题标题】:How to animate changing innerHTML?如何动画变化的innerHTML?
【发布时间】:2020-07-19 17:45:17
【问题描述】:

有一个小程序,可以动态地将单词拉伸到任何屏幕高度。它基于innerHTML。当单词发生变化时,如何使其淡入淡出?

let text = document.getElementById("text");
let input = document.getElementById("input");
let svg = document.querySelector("svg");
function changeWord() {
  text.innerHTML = input.value;
  svg.setAttributeNS(null, "viewBox", `-4 0 16 ${text.getComputedTextLength()}`);
}
* {
  padding: 0;
  margin: 0;
}

svg {
  height: 100vh;
  font-family: roboto, sans-serif;
  font-size:16px;
  border:1px solid;
}

input {
  position: fixed;
  top: 0;
  right: 0;
  border: 2px solid red;
}
<svg viewBox="-4 0 16 75">
  <g transform="rotate(90 0 0)">
  <text id="text">Skibpidi</text>
  </g>
</svg>

<input value="Skibidi" oninput="changeWord()" id="input" type="text">

【问题讨论】:

  • 设置元素的内部 HTML 不是动画过程。
  • 是否可以将其更改为其他可以动画的方法或属性?
  • 您可以在同一位置创建一个新元素,将其淡入并淡出旧元素。或者您可以淡出,更改innerHTML,然后淡入。

标签: javascript html css svg


【解决方案1】:

我将添加的字符包装在 &lt;tspan&gt; 元素中。 tspan 在 css 中从 fill-opacity:0fill-opacity:1 进行动画处理,以实现淡入效果。请阅读代码中的cmets。

const SVG_NS = "http://www.w3.org/2000/svg";

let text = document.getElementById("text");
let input = document.getElementById("input");
let svg = document.querySelector("svg");
let L; //the number of letters of the input value

function setWord() {
  let vals = input.value.trim().split(""); //trim for the empty spaces at the begining and the end of the string and split into an array
  L = vals.length; //the length of the array == the number of letters
  text.innerHTML = ""; //clear the content of the text element

  // set a variable for the text content
  let textcontent = "";
  vals.forEach((v) => {
    //add each value to the textcontent
    textcontent += v;
  });

  text.textContent = textcontent;
  //reset the viewBox value
  svg.setAttributeNS(
    null,
    "viewBox",
    `-4 0 16 ${text.getComputedTextLength()}`
  );
}

setWord();

function changeWord(e) {
  let vals = input.value.trim().split("");
  if (vals.length == L + 1) {
    // if the user is adding chars to the input
    //create a new element tspan to wrap the new character in
    let tspan = document.createElementNS(SVG_NS, "tspan");
    //set the text content of the tspan element
    tspan.textContent = vals[vals.length - 1];
    //append the tspan to the text element
    text.appendChild(tspan);
    // reset the value of the L
    L += 1;
  } else {
    //if the user is deleting letters
    setWord();
  }
  //reset the viewBox value
  svg.setAttributeNS(
    null,
    "viewBox",
    `-4 0 16 ${text.getComputedTextLength()}`
  );
}

input.addEventListener("input", changeWord);
* {
  padding: 0;
  margin: 0;
}

svg {
  height: 100vh;
  font-family: roboto, sans-serif;
  font-size:16px;
  border:1px solid;
}

input {
  position: fixed;
  top: 0;
  right: 0;
  border: 2px solid red;
}

tspan{
fill-opacity:0;
animation: fo 2s forwards;
}


@keyframes fo{
  to{fill-opacity:1;}
}
<svg viewBox="-4 0 16 75">
  <g transform="rotate(90 0 0)">
  <text id="text">Skibpidi</text>
  </g>
</svg>

<input value="Skibidi" id="input" type="text">

【讨论】:

    【解决方案2】:

    有必要使用svg吗?只有你可以这样做:

    let text = document.getElementById("text");
    let input = document.getElementById("input");
    
    function changeWord(event) {
      let letter = document.createElement('div');
      letter.className = 'letter'
    
      // Handle delete key
      if (event.key === 'Backspace' && text.childElementCount > 0) {
        text.removeChild(text.lastChild);
      } else {
      // Assign last letter of the input to created div
        letter.innerHTML = input.value.slice(input.value.length - 1,
          input.value.length);
        text.appendChild(letter);
      }
    }
    * {
      padding: 0;
      margin: 0;
    }
    
    #text {
      display: flex;
      height: 100vh;
      font-family: roboto, sans-serif;
      font-size: 16px;
      border: 1px solid;
    }
    
    .letter {
      /* Allow spaces */
      white-space: break-spaces;
      transform: translateY(20px);
      animation: slide 1s forwards cubic-bezier(0.4, 0.6, 0.8, 0.9);
    }
    
    @keyframes slide {
      0% {
        transform: translateY(20px);
      }
      100% {
        transform: translateY(0px);
      }
    }
    
    input {
      position: fixed;
      top: 0;
      right: 0;
      border: 2px solid red;
    }
    <div id="text">
      <div class="letter">S</div>
      <div class="letter">k</div>
      <div class="letter">i</div>
      <div class="letter">b</div>
      <div class="letter">p</div>
      <div class="letter">i</div>
      <div class="letter">d</div>
      <div class="letter">i</div>
    </div>
    
    <input value="Skibidi" onkeyup="changeWord(event)" id="input" type="text">

    请记住,您必须按照自己的意愿设置样式。

    【讨论】:

    • 不太清楚,快速打字时字母不匹配,2x 退格删除初始字母。
    • 你说得对,这是我能想到的最好的,不知道还有什么建议
    • 别告诉我这是你能做的最好的,士兵!你可以做得更好,只是时间不合适,因为现在是星期五。
    猜你喜欢
    • 2013-04-17
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    相关资源
    最近更新 更多