You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中如何实现textarea逐字逐词逐行动画效果及钢笔光标模拟

问题修复实现方案

原方案失效原因

参考的demo是针对普通DOM元素实现的动画,核心逻辑是将文本拆分为独立<span>标签,通过控制每个标签的透明度、位移实现动效。但<textarea>属于可替换元素,内部仅支持纯文本,无法解析嵌套HTML标签,因此直接复用原有CSS类会完全失效。

适配textarea的动画实现

我们改用动态拼接textarea.value属性的方式实现三类动画效果,具体实现如下:

基础结构

<div class="textarea-wrapper">
  <textarea id="animTextarea" rows="10" cols="50"></textarea>
  <!-- 钢笔光标元素 -->
  <div class="pen-cursor"></div>
</div>

样式代码

.textarea-wrapper {
  position: relative;
  display: inline-block;
}
#animTextarea {
  font-size: 16px;
  line-height: 1.8;
  padding: 8px;
  caret-color: transparent; /* 隐藏原生光标 */
  outline: none;
  border: 1px solid #eee;
}
.pen-cursor {
  position: absolute;
  width: 18px;
  height: 26px;
  left: 10px;
  top: 10px;
  pointer-events: none;
  transition: all 0.08s linear;
  /* 钢笔图标,可替换为自定义样式 */
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23222"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>') no-repeat center/contain;
}

功能逻辑代码

const textarea = document.getElementById('animTextarea');
const cursor = document.querySelector('.pen-cursor');
const lineHeight = parseInt(getComputedStyle(textarea).lineHeight);
const paddingLeft = parseInt(getComputedStyle(textarea).paddingLeft);
const paddingTop = parseInt(getComputedStyle(textarea).paddingTop);

// 待展示的文本内容
const fullContent = `第一行演示文本
第二行测试逐词展示效果
第三行可以写更长的内容验证自动滚动
第四行结束动画`;

// 动画配置
const animConfig = {
  // 动画模式:char逐字 / word逐词 / line逐行
  mode: 'char',
  // 每个单元动画间隔,单位ms
  interval: 80,
  // 是否展示钢笔光标
  showCursor: true
};

// 光标位置同步方法
function updateCursorPosition() {
  const lineNum = textarea.value.substr(0, textarea.selectionEnd).split('\n').length;
  const colNum = textarea.value.substr(0, textarea.selectionEnd).split('\n').pop().length;
  // 计算坐标,1px是字体宽度偏移,可根据实际字体调整
  cursor.style.left = `${paddingLeft + colNum * 8 + 1}px`;
  cursor.style.top = `${paddingTop + (lineNum - 1) * lineHeight}px`;
  textarea.scrollTop = textarea.scrollHeight;
}

// 动画启动方法
async function runTextAnimation() {
  textarea.value = '';
  let contentUnits = [];

  // 按配置拆分文本单元
  if (animConfig.mode === 'line') {
    contentUnits = fullContent.split('\n').map(line => line + '\n');
  } else if (animConfig.mode === 'word') {
    contentUnits = fullContent.split(/(\s|\n)/);
  } else {
    contentUnits = fullContent.split('');
  }

  for (const unit of contentUnits) {
    textarea.value += unit;
    textarea.selectionEnd = textarea.value.length;
    if (animConfig.showCursor) updateCursorPosition();
    await new Promise(resolve => setTimeout(resolve, animConfig.interval));
  }
}

// 启动动画
runTextAnimation();

扩展说明

如果需要沿用原demo的animejs缓动效果,可将文本拼接逻辑封装到anime实例的update回调中,通过动画进度控制当前展示的文本长度,即可匹配原demo的动画节奏。

内容的提问来源于stack exchange,提问作者Kris Swat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:06:05