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

如何在Canvas滚动动画结束后添加可滚动的后续内容?

问题解决:Canvas动画后显示后续内容并保持滚动条

核心问题分析

  1. CSS中content选择器写错,遗漏类选择器的点号,导致内容样式完全不生效
  2. .content定位为absolute脱离文档流,无法正常占据页面空间,滚动后看不到内容
  3. 内容区域未设置足够高度,无法保证页面加载时就出现滚动条

修改方案


1. 修正CSS选择器与内容布局

把错误的content选择器改为.content,将定位改为relative让内容回到文档流,同时设置宽度和最小高度,确保页面有足够滚动空间:

.content {
  position: relative;
  width: 100%;
  background: #000;
  color: #fff;
  padding: 20px 0;
  text-align: center;
  margin-top: 100vh;
  min-height: 100vh; /* 保证内容至少占一屏高度,加载时就有滚动条 */
  opacity: 0;
  transition: opacity 1s ease-in-out;
}

2. 调整层级关系

给Canvas、overlay、内容添加层级,确保动画期间Canvas和overlay在内容上方,动画结束后内容正常显示:

canvas {
  /* 原有样式 */
  z-index: 10;
}

.overlay {
  /* 原有样式 */
  z-index: 20;
}

.content {
  /* 原有样式 */
  z-index: 5;
}

3. 优化动画结束后的内容显示逻辑

动画结束后隐藏overlay和标题,让内容完全展示:

if (frameIndex === frameCount - 1) {
  canvas.style.transition = 'opacity 1s ease-in-out';
  canvas.style.opacity = '0';
  overlay.classList.add('visible');
  message.classList.add('visible');

  setTimeout(() => {
    content.classList.add('visible');
    overlay.classList.remove('visible');
    message.classList.remove('visible');
  }, 1000);
}

修改后的完整代码

HTML

<canvas width="300" height="200" class="ultragear-scrolling"></canvas>
<div class="overlay">
  <h1 class="message">Ultra Gear </h1>
</div>
<div class="content">
  <h2>Additional Content</h2>
  <img src="https://gi.esmplus.com/BLADER01/Hyuk/27gs95qe/27gs95qe_01.png" alt="Additional Image" />
</div>

CSS

html {
  height: 2000vh;
}

body {
  background: #000;
  height: 2000vh;
  margin: 0;
}

canvas {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  max-height: 100vh;
  max-width: 100vw;
  z-index: 10;
}

.overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 0;
  transition: opacity 1s ease-in-out;
  pointer-events: none;
  background: #000;
  z-index: 20;
}

.message {
  color: #fff;
  font-size: 2rem;
  transform: scale(0);
  transition: transform 1s ease-in-out;
}

.overlay.visible {
  opacity: 1;
}

.message.visible {
  transform: scale(1);
}

.content {
  position: relative;
  width: 100%;
  background: #000;
  color: #fff;
  padding: 20px 0;
  text-align: center;
  margin-top: 100vh;
  min-height: 100vh;
  opacity: 0;
  transition: opacity 1s ease-in-out;
  z-index: 5;
}

.content.visible {
  opacity: 1;
}

JavaScript

const html = document.documentElement;
const canvas = document.querySelector('.ultragear-scrolling');
const context = canvas.getContext('2d');
const overlay = document.querySelector('.overlay');
const message = document.querySelector('.message');
const content = document.querySelector('.content');

const currentFrame = index => (
  `https://gi.esmplus.com/BLADER01/Hyuk/oled-moon/${index.toString().padStart(0, '1')}.jpg`
);

const frameCount = 294;

canvas.height = 770;
canvas.width = 1158;

const images = [];

const preloadImages = () => {
  for (let i = 1; i <= frameCount; i++) {
    const img = new Image();
    img.src = currentFrame(i);
    images.push(img);
  }
};

preloadImages();

const img = new Image();
img.src = currentFrame(1);
img.onload = function() {
  drawCentered(img);
}

const updateImage = index => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  drawCentered(images[index]);
};

function drawCentered(img) {
  const offsetX = (canvas.width - img.width) / 2;
  const offsetY = (canvas.height - img.height) / 2;
  context.drawImage(img, offsetX, offsetY);
}

let animationFrameId;

window.addEventListener('scroll', () => {
  cancelAnimationFrame(animationFrameId);

  const scrollTop = html.scrollTop;
  const maxScrollTop = html.scrollHeight - window.innerHeight;
  const scrollFraction = scrollTop / maxScrollTop;
  const frameIndex = Math.min(
    frameCount - 1,
    Math.floor(scrollFraction * frameCount)
  );

  animationFrameId = requestAnimationFrame(() => updateImage(frameIndex));

  if (frameIndex === frameCount - 1) {
    canvas.style.transition = 'opacity 1s ease-in-out';
    canvas.style.opacity = '0';
    overlay.classList.add('visible');
    message.classList.add('visible');

    setTimeout(() => {
      content.classList.add('visible');
      overlay.classList.remove('visible');
      message.classList.remove('visible');
    }, 1000);
  } else {
    canvas.style.opacity = '1';
    overlay.classList.remove('visible');
    message.classList.remove('visible');
    content.classList.remove('visible');
  }
});

内容的提问来源于stack exchange,提问作者HK L

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:10:53