feat(miniprogram): 沉浸式自定义导航+统一固定标题区
- 五个 tab 页 navigationStyle=custom,内容直通状态栏(去白色页眉) - TopInset/PageHeader 组件:状态栏+胶囊安全区实测;标题区(像素字kicker+彩虹渐变标题+像素字注脚)四页同构、fixed 不随滚动 - 占位高度 createSelectorQuery 实测 navbar 真实高度,无空白/覆盖/重复 - 标题区上移 65rpx(从状态栏让位空间扣除,非容器偏移)
This commit is contained in:
@@ -394,3 +394,22 @@ page { -ms-overflow-style: none; scrollbar-width: none; }
|
||||
.ic-shield { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Cpath d='M12 3l8 3v5c0 5-3.5 8-8 10-4.5-2-8-5-8-10V6z'/%3E%3Cpath d='M9 12l2 2 4-4'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Cpath d='M12 3l8 3v5c0 5-3.5 8-8 10-4.5-2-8-5-8-10V6z'/%3E%3Cpath d='M9 12l2 2 4-4'/%3E%3C/svg%3E"); }
|
||||
.ic-landmark { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Cpath d='M3 10l9-6 9 6'/%3E%3Cpath d='M5 10v9M9.5 10v9M14.5 10v9M19 10v9M3 20h18'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Cpath d='M3 10l9-6 9 6'/%3E%3Cpath d='M5 10v9M9.5 10v9M14.5 10v9M19 10v9M3 20h18'/%3E%3C/svg%3E"); }
|
||||
.ic-users { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Ccircle cx='9' cy='8' r='3.5'/%3E%3Cpath d='M2.5 20a6.5 6.5 0 0 1 13 0'/%3E%3Cpath d='M15.5 5a3.5 3.5 0 0 1 0 6.6'/%3E%3Cpath d='M17.5 14.4a6.5 6.5 0 0 1 4 5.6'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.5'%3E%3Ccircle cx='9' cy='8' r='3.5'/%3E%3Cpath d='M2.5 20a6.5 6.5 0 0 1 13 0'/%3E%3Cpath d='M15.5 5a3.5 3.5 0 0 1 0 6.6'/%3E%3Cpath d='M17.5 14.4a6.5 6.5 0 0 1 4 5.6'/%3E%3C/svg%3E"); }
|
||||
|
||||
/* ============ 统一固定标题区(像素字 kicker + 彩虹渐变标题 + 像素字注脚) ============ */
|
||||
.page-navbar {
|
||||
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
|
||||
padding: 0 28rpx; /* 标题区上下零冗余:高度 = 安全区 + 三行文字,占位实测自然贴合 */
|
||||
background: rgba(247, 249, 255, 0.88);
|
||||
backdrop-filter: blur(20px) saturate(160%);
|
||||
-webkit-backdrop-filter: blur(20px) saturate(160%);
|
||||
}
|
||||
.page-navbar-col { display: flex; flex-direction: column; }
|
||||
.page-navbar-no { font-family: 'BubbledotICG', monospace; color: #a3abc9; font-size: 26rpx; letter-spacing: 2rpx; line-height: 1.15; }
|
||||
.page-navbar-titlerow { display: flex; align-items: baseline; gap: 16rpx; line-height: 1.15; }
|
||||
.page-navbar-title {
|
||||
font-size: 40rpx; font-weight: 800; letter-spacing: -0.5rpx; line-height: 1.15;
|
||||
background: linear-gradient(120deg, #8fc3ff 0%, #a8a0ff 45%, #e0a0ff 80%, #7fe0ff 100%);
|
||||
-webkit-background-clip: text; background-clip: text; color: transparent;
|
||||
}
|
||||
.page-navbar-sub { font-size: 24rpx; color: #5a6aa3; }
|
||||
.page-navbar-en { font-family: 'BubbledotICG', monospace; color: #5b5b5b; font-size: 24rpx; letter-spacing: 2rpx; line-height: 1.15; padding-bottom: 12rpx; }
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
let cached = null;
|
||||
|
||||
/** 顶部安全区(沉浸式自定义导航用):状态栏 + 胶囊高度。 */
|
||||
export function getTopInset() {
|
||||
if (!cached) {
|
||||
try {
|
||||
const win = Taro.getWindowInfo ? Taro.getWindowInfo() : Taro.getSystemInfoSync();
|
||||
const statusBar = win.statusBarHeight || 44;
|
||||
const windowWidth = win.windowWidth || 375;
|
||||
let navH = statusBar + 44;
|
||||
try {
|
||||
const menu = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null;
|
||||
if (menu && menu.height) navH = statusBar + (menu.top - statusBar) * 2 + menu.height;
|
||||
} catch { /* 无胶囊环境用默认 */ }
|
||||
cached = { statusBar, navH, windowWidth };
|
||||
} catch {
|
||||
cached = { statusBar: 44, navH: 88, windowWidth: 375 };
|
||||
}
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
/** 统一固定标题区(fixed 不随滚动):像素字 kicker + 彩虹渐变标题 + 像素字注脚。
|
||||
* 占位高度由 createSelectorQuery 实测 navbar 真实高度,绝无空白/覆盖/重复。 */
|
||||
export function PageHeader({ no, title, en, sub }) {
|
||||
const { navH, windowWidth } = getTopInset();
|
||||
// 标题区整体上移 65rpx:从状态栏让位空间中扣除(不是容器偏移,占位实测自动跟随,无空白)
|
||||
const SHIFT_PX = Math.round((65 * (windowWidth || 375)) / 750);
|
||||
const topPad = Math.max(navH - SHIFT_PX, 24); // 下限:至少给状态栏留 24px
|
||||
const [h, setH] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
Taro.nextTick(() => {
|
||||
Taro.createSelectorQuery()
|
||||
.select('.page-navbar')
|
||||
.boundingClientRect((r) => { if (r && r.height) setH(r.height); })
|
||||
.exec();
|
||||
});
|
||||
}, [no, title, en, sub]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<View className="page-navbar" style={{ paddingTop: `${topPad}px` }}>
|
||||
<View className="page-navbar-col">
|
||||
{no ? <Text className="page-navbar-no">{no}</Text> : null}
|
||||
<View className="page-navbar-titlerow">
|
||||
<Text className="page-navbar-title">{title}</Text>
|
||||
{sub ? <Text className="page-navbar-sub">{sub}</Text> : null}
|
||||
</View>
|
||||
{en ? <Text className="page-navbar-en">{en}</Text> : null}
|
||||
</View>
|
||||
</View>
|
||||
<View style={{ height: `${h}px` }} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/** 沉浸式顶部占位:配合页面 navigationStyle=custom 使用。 */
|
||||
export default function TopInset() {
|
||||
const { navH } = getTopInset();
|
||||
return <View style={{ height: `${navH}px` }} />;
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
export default { navigationBarTitleText: '活动' };
|
||||
export default { navigationBarTitleText: '活动', navigationStyle: 'custom' };
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default { navigationBarTitleText: '资讯中心' };
|
||||
export default { navigationBarTitleText: '资讯中心', navigationStyle: 'custom' };
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default { navigationBarTitleText: 'OPC · 为进化而设计' };
|
||||
export default { navigationBarTitleText: 'OPC · 为进化而设计', navigationStyle: 'custom' };
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default { navigationBarTitleText: '我的' };
|
||||
export default { navigationBarTitleText: '我的', navigationStyle: 'custom' };
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default { navigationBarTitleText: 'OPC 创业测评' };
|
||||
export default { navigationBarTitleText: 'OPC 创业测评', navigationStyle: 'custom' };
|
||||
|
||||
Reference in New Issue
Block a user