我们所说的沉浸式背景图通常指的是在移动端或Web端,将背景图与顶部导航栏或状态栏融合,使得背景图看起来像是延伸到状态栏或导航栏之下,从而实现一种沉浸式的视觉体验。在移动端,这通常涉及到将内容延伸到状态栏(显示时间、电量等的区域)下方,使得背景图覆盖整个上半部分屏幕。
沉浸式示例
| 某红书 | 某象超市 |
|---|---|
核心特征
- 全宽覆盖:占满屏幕宽度
- 顶部延伸:与状态栏/导航栏融合
- 内容叠加:文字、按钮等浮在背景图上
- 滚动联动:随滚动动态变化/隐藏
常见效果
初始状态:
┌─────────────────┐
│ 🌄🌄🌄🌄🌄🌄 │ ← 背景图延伸到状态栏下
│ 🌄🌄🌄🌄🌄🌄 │
│ 🏷️ 标题 │ ← 内容浮在背景图上
│ 🧭 导航 │
├─────────────────┤
│ 正文内容 │
└─────────────────┘
滚动后:
┌─────────────────┐
│ 🧭 导航栏 │ ← 背景图缩小/隐藏
├─────────────────┤
│ 🌄🌄 │ ← 可能保留部分背景
│ 正文内容 │
└─────────────────┘
沉浸式实现原理
- 背景图处理:背景图需要延伸至状态栏,并始终位于导航栏,活动文案等元素下方;
- 滚动交互:随着用户上滑行为,背景图逐渐隐藏,实现平滑过渡;
- 性能优化:沉浸式背景图体积往往较大,需要考虑图片加载优化;
关键要素
独立的背景元素
- 在页面元素顶部新增独立的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);
}
}, [依赖项]);
以上是核心两点,其余部分日后补充...