小程序沉浸式效果实现

60 阅读2分钟

我们所说的沉浸式背景图通常指的是在移动端或Web端,将背景图与顶部导航栏或状态栏融合,使得背景图看起来像是延伸到状态栏或导航栏之下,从而实现一种沉浸式的视觉体验。在移动端,这通常涉及到将内容延伸到状态栏(显示时间、电量等的区域)下方,使得背景图覆盖整个上半部分屏幕。

沉浸式示例

某红书某象超市
image.pngimage.png

核心特征

  • 全宽覆盖:占满屏幕宽度
  • 顶部延伸:与状态栏/导航栏融合
  • 内容叠加:文字、按钮等浮在背景图上
  • 滚动联动:随滚动动态变化/隐藏

常见效果

初始状态:
┌─────────────────┐
│  🌄🌄🌄🌄🌄🌄     │ ← 背景图延伸到状态栏下
│  🌄🌄🌄🌄🌄🌄     │
│   🏷️ 标题        │ ← 内容浮在背景图上
│   🧭 导航        │
├─────────────────┤
│    正文内容      │
└─────────────────┘

滚动后:
┌─────────────────┐
│  🧭 导航栏       │ ← 背景图缩小/隐藏
├─────────────────┤
│  🌄🌄            │ ← 可能保留部分背景
│    正文内容      │
└─────────────────┘

沉浸式实现原理

  • 背景图处理:背景图需要延伸至状态栏,并始终位于导航栏,活动文案等元素下方;
  • 滚动交互:随着用户上滑行为,背景图逐渐隐藏,实现平滑过渡;
  • 性能优化:沉浸式背景图体积往往较大,需要考虑图片加载优化;

关键要素

独立的背景元素

  • 在页面元素顶部新增独立的div元素用于展示背景图,采用绝对定位,确保其它元素位于背景图上方。
  • 图片高度采用动态计算的方式;
  • 隐藏动效简单采用opacity和transition实现;
        <View
          id='floors-background-image'
          style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: bgHeight, // 使用动态计算的高度
            backgroundImage: `url(${imgUrl})`,
            backgroundSize: 'cover',
            backgroundPosition: 'bottom center', // 从底部开始对齐
            backgroundRepeat: 'no-repeat',
            pointerEvents: 'none', // 不阻止用户交互
            opacity: isSticky ? 0 : 1, // 根据isSticky实现背景图隐藏动效
            transition: 'opacity 0.3s ease-in-out',
          }}
        />

若要考虑沉浸式背景加载失败的兜底情形,可以将View替换为Image组件,用内置的onError方法处理加载失败的情况;

        <Image
          id='floors-background-image'
          src={imgUrl}
          style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: bgHeight, // 使用动态计算的高度
            backgroundSize: 'cover',
            backgroundPosition: 'top center', // 从顶部开始对齐
            backgroundRepeat: 'no-repeat',
            pointerEvents: 'none', // 不阻止用户交互
            opacity: isSticky ? 0 : 1, // 根据isSticky实现背景图隐藏动效
            transition: 'opacity 0.1s ease-in-out',
          }}
          onError={() => {
            setImageLoadError(true);
          }}
        />

动态高度计算

以Taro框架为例,在目标元素渲染后查询元素高度。

  // 获取元素高度
  useEffect(() => {
    try {
      const domId = 'xxxx';
      // 使用promise保证查询到元素之后再计算高度
      const getElementRect = (selector) => {
        return new Promise((resolve) => {
          Taro.createSelectorQuery()
            .select(`#${selector}`)
            .boundingClientRect(resolve)
            .exec();
        });
      };
      getElementRect(domId).then((dom) => {
        // 确保存在才计算
        if (dom) {
          setBgHeight(dom?.top);
        }
      });
    } catch (error) {
      console.log('计算背景图高度时出错:', error);
    }
  }, [依赖项]);

以上是核心两点,其余部分日后补充...