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

如何优化约1000个带CSS动画div的生成加载速度?

优化全屏点阵动画加载速度的方案

我正在制作个人作品集网站,为首页添加了全屏点阵动画效果。目前功能正常,但动画加载耗时过长。通过JS生成25x25的div矩阵,并为每个div添加CSS样式与动画。已尝试减小矩阵尺寸,但优化效果有限,进一步缩小则无法覆盖整个页面,求优化加载速度的方案。

现有代码

JavaScript

let holder = document.getElementById("hero");

let gs = 25;

window.onload = () => {
  for (let i = 0; i < gs; i++) {
    for (let j = 0; j < gs; j++) {
      let dot = document.createElement("div");
      dot.classList.add("dot");
      dot.style.animationDelay = `${Math.sin(i * j) / 2}s`;
      holder.appendChild(dot);
    }
  }
};

CSS

.hero {
  /* background-image: url(media/Background.jpg); */
  height: 100vh;
  position: absolute;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(50, 90px);
  grid-template-rows: repeat(50, 90px);
  overflow: hidden;
  text-align: left;
}

.dot {
  width: 2px;
  height: 2px;
  animation-name: wavyDots;
  animation-duration: 1s;
  animation-iteration-count: infinite;
  animation-direction: alternate-reverse;
  z-index: -1;
}

.dot:nth-child(odd) {
  background-color: #0cf5d5;
}

.dot:nth-child(even) {
  background-color: #e0017a;
}

@keyframes wavyDots {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(30px, 30px);
  }
}

优化方案

1. 用DocumentFragment批量插入DOM,减少重排

每次调用appendChild都会触发浏览器重排,改用DocumentFragment一次性插入所有节点,大幅减少渲染阻塞:

window.onload = () => {
  let fragment = document.createDocumentFragment();
  for (let i = 0; i < gs; i++) {
    for (let j = 0; j < gs; j++) {
      let dot = document.createElement("div");
      dot.classList.add("dot");
      dot.style.animationDelay = `${Math.sin(i * j) / 2}s`;
      fragment.appendChild(dot);
    }
  }
  holder.appendChild(fragment); // 仅一次DOM插入操作
};

2. 匹配Grid布局与实际点阵数量

当前Grid设置为repeat(50, 90px),但实际只生成25x25个点,布局规则与元素数量不匹配会浪费渲染资源,修改为:

.hero {
  /* 其他样式保持不变 */
  display: grid;
  grid-template-columns: repeat(25, 1fr); /* 和生成的列数一致 */
  grid-template-rows: repeat(25, 1fr);
}

3. 开启GPU加速,优化动画性能

给.dot添加will-change属性提示浏览器提前准备动画加速;用translate3d替代translate,强制触发GPU渲染:

.dot {
  /* 其他样式保持不变 */
  will-change: transform;
}

@keyframes wavyDots {
  0% {
    transform: translate3d(0, 0, 0);
  }
  100% {
    transform: translate3d(30px, 30px, 0);
  }
}

4. 改用Canvas渲染(性能最优方案)

大量DOM节点的动画性能远不如Canvas,用Canvas绘制点阵并实现动画,能减少90%以上的性能消耗:

window.onload = () => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const hero = document.getElementById('hero');
  
  // 设置Canvas尺寸为容器大小
  canvas.width = hero.offsetWidth;
  canvas.height = hero.offsetHeight;
  canvas.style.cssText = 'position:absolute;top:0;left:0;z-index:-1;';
  hero.appendChild(canvas);
  
  const dotSize = 2;
  const gridSize = 25;
  const dotSpacingX = canvas.width / gridSize;
  const dotSpacingY = canvas.height / gridSize;
  const dots = [];
  
  // 初始化点阵数据
  for (let i = 0; i < gridSize; i++) {
    for (let j = 0; j < gridSize; j++) {
      const delay = Math.sin(i * j) / 2;
      dots.push({
        x: j * dotSpacingX,
        y: i * dotSpacingY,
        color: (i * gridSize + j) % 2 === 0 ? '#e0017a' : '#0cf5d5',
        delay: delay,
        startTime: performance.now() + delay * 1000
      });
    }
  }
  
  // 动画循环
  function animate(timestamp) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    dots.forEach(dot => {
      if (timestamp < dot.startTime) return;
      
      // 计算动画进度,模拟CSS的alternate-reverse效果
      const elapsed = (timestamp - dot.startTime) % 1000;
      const progress = elapsed / 1000;
      const finalProgress = progress < 0.5 ? progress * 2 : (1 - progress) * 2;
      
      const currentX = dot.x + 30 * finalProgress;
      const currentY = dot.y + 30 * finalProgress;
      
      ctx.fillStyle = dot.color;
      ctx.fillRect(currentX, currentY, dotSize, dotSize);
    });
    
    requestAnimationFrame(animate);
  }
  
  // 监听窗口 resize,同步Canvas尺寸
  window.addEventListener('resize', () => {
    canvas.width = hero.offsetWidth;
    canvas.height = hero.offsetHeight;
  });
  
  requestAnimationFrame(animate);
};

使用该方案时,需移除原.hero的Grid样式及所有.dot相关CSS。

补充说明

  • Canvas方案性能优势极大,即使将网格扩大到50x50也不会出现明显卡顿;
  • 若坚持使用DOM方案,优先采用DocumentFragment批量插入+GPU加速的组合优化;
  • Canvas方案需添加窗口resize监听,确保点阵始终覆盖全屏。

内容的提问来源于stack exchange,提问作者Topu Rayhan Rabby Mamud

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:15:33