瀏覽代碼

feat: 微信下,导航栏渐变效果

Burt 2 年之前
父節點
當前提交
356488106c
共有 4 個文件被更改,包括 135 次插入10 次删除
  1. 5 4
      src/components/fly-navbar/fly-navbar.vue
  2. 62 0
      src/hooks/useNavbarWeixin.ts
  3. 3 0
      src/pages/index/index.vue
  4. 65 6
      src/pages/my/index.vue

+ 5 - 4
src/components/fly-navbar/fly-navbar.vue

@@ -8,14 +8,14 @@
     <!-- 2/3,只有1个页面,如果不是tabbar,需要首页图标 -->
     <!-- 这种情况一般出现在用户直接打开分享出去的详情页面,或者使用redirectTo等API -->
     <navigator
-      v-else-if="isTabbar"
+      v-else-if="!isTabbar"
       open-type="switchTab"
       url="/pages/index/index"
       class="left-icon"
     >
       <button class="i-carbon-home text-white"></button>
     </navigator>
-    <!-- 如果当前页就是tabbar页,不用去首页,也就是什么图标都不需要 -->
+    <!-- 3/3,如果当前页就是tabbar页,不用去首页,也就是什么图标都不需要 -->
     <view class="title">{{ title || '' }}</view>
   </view>
 </template>
@@ -24,11 +24,12 @@
 import { getIsTabbar } from '@/utils/index'
 
 defineProps<{ title?: string }>()
-// 获取屏幕边界到安全区域距离
-const { safeAreaInsets } = uni.getSystemInfoSync()
 // 获取页面栈
 const pages = getCurrentPages()
 const isTabbar = getIsTabbar()
+
+// 获取屏幕边界到安全区域距离
+const { safeAreaInsets } = uni.getSystemInfoSync()
 </script>
 
 <style lang="scss" scoped>

+ 62 - 0
src/hooks/useNavbarWeixin.ts

@@ -0,0 +1,62 @@
+import { onReady } from '@dcloudio/uni-app'
+import { getIsTabbar } from '@/utils/index'
+
+export default () => {
+  // 获取页面栈
+  const pages = getCurrentPages()
+  const isTabbar = getIsTabbar()
+
+  // 页面滚动到底部时的操作,通常用于加载更多数据
+  const onScrollToLower = () => {}
+  // 获取屏幕边界到安全区域距离
+  const { safeAreaInsets } = uni.getSystemInfoSync()
+
+  // #ifdef MP-WEIXIN
+  // 基于小程序的 Page 类型扩展 uni-app 的 Page
+  type PageInstance = Page.PageInstance & WechatMiniprogram.Page.InstanceMethods<any>
+  // 获取当前页面实例,数组最后一项
+  const pageInstance = getCurrentPages().at(-1) as PageInstance
+
+  // 页面渲染完毕,绑定动画效果
+  onReady(() => {
+    // 动画效果,导航栏背景色
+    pageInstance.animate(
+      '.fly-navbar',
+      [{ backgroundColor: 'transparent' }, { backgroundColor: '#f8f8f8' }],
+      1000,
+      {
+        scrollSource: '#scroller',
+        timeRange: 1000,
+        startScrollOffset: 0,
+        endScrollOffset: 50,
+      },
+    )
+    // 动画效果,导航栏标题
+    pageInstance.animate(
+      '.fly-navbar .title',
+      [{ color: 'transparent' }, { color: '#000' }],
+      1000,
+      {
+        scrollSource: '#scroller',
+        timeRange: 1000,
+        startScrollOffset: 0,
+        endScrollOffset: 50,
+      },
+    )
+    // 动画效果,导航栏返回按钮
+    pageInstance.animate('.fly-navbar .left-icon', [{ color: '#fff' }, { color: '#000' }], 1000, {
+      scrollSource: '#scroller',
+      timeRange: 1000,
+      startScrollOffset: 0,
+      endScrollOffset: 50,
+    })
+  })
+  // #endif
+
+  return {
+    pages,
+    isTabbar,
+    onScrollToLower,
+    safeAreaInsets,
+  }
+}

+ 3 - 0
src/pages/index/index.vue

@@ -17,6 +17,9 @@
     <!-- Sun in light mode, Moon in dark mode, from Carbon -->
     <button class="i-carbon-sun dark:i-carbon-moon text-green-300" />
     <fly-header></fly-header>
+    <navigator url="/pages/test1/index" open-type="navigate" hover-class="navigator-hover">
+      去二级页
+    </navigator>
   </view>
 </template>
 

+ 65 - 6
src/pages/my/index.vue

@@ -1,9 +1,26 @@
 <template>
-  <fly-navbar title="导航栏标题" />
+  <view class="fly-navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
+    <!-- 1/3,多于1个页面,用返回图标 -->
+    <navigator v-if="pages.length > 1" open-type="navigateBack" class="left-icon">
+      <button class="i-carbon-chevron-left text-current"></button>
+    </navigator>
+    <!-- 2/3,只有1个页面,如果不是tabbar,需要首页图标 -->
+    <!-- 这种情况一般出现在用户直接打开分享出去的详情页面,或者使用redirectTo等API -->
+    <navigator
+      v-else-if="!isTabbar"
+      open-type="switchTab"
+      url="/pages/index/index"
+      class="left-icon"
+    >
+      <button class="i-carbon-home text-current"></button>
+    </navigator>
+    <!-- 3/3,如果当前页就是tabbar页,不用去首页,也就是什么图标都不需要 -->
+    <view class="title">{{ '我是标题' }}</view>
+  </view>
   <scroll-view
     enable-back-to-top
     scroll-y
-    class="bg-zinc-100"
+    class="bg-white flex-1 h-full"
     id="scroller"
     @scrolltolower="onScrollToLower"
   >
@@ -12,18 +29,29 @@
       <view>可以是标题,也可以是个人中心头像等</view>
       <view>建议本区域高度不低于200rpx</view>
     </view>
+    <view class="p-2 leading-6">
+      注意,上面的导航栏渐变效果仅微信端支持,且上面的导航栏无法抽为组件引入使用,否则滚动效果没有了。如果不只是微信小程序使用,可以
+      onPageScroll 实现全端效果一样,另外如果是app端,还可以配置 titleNView。参考
+      https://uniapp.dcloud.net.cn/tutorial/page.html#onpagescroll 。
+    </view>
     <fly-content :line="30" />
   </scroll-view>
 </template>
 
 <script lang="ts" setup>
-// 页面滚动到底部时的操作,通常用于加载更多数据
-const onScrollToLower = () => {}
-// 获取屏幕边界到安全区域距离
-const { safeAreaInsets } = uni.getSystemInfoSync()
+import useNavbarWeixin from '@/hooks/useNavbarWeixin'
+
+const { pages, isTabbar, onScrollToLower, safeAreaInsets } = useNavbarWeixin()
 </script>
 
 <style lang="scss">
+page {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  overflow: hidden;
+}
+
 // 这个区域最好要大于200rpx,效果会更好
 .top-section {
   display: flex;
@@ -36,4 +64,35 @@ const { safeAreaInsets } = uni.getSystemInfoSync()
   background-image: url('https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/top-bg.png');
   background-size: cover;
 }
+
+.fly-navbar {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 9;
+  width: 750rpx;
+  color: #000;
+  background-color: transparent;
+
+  .left-icon {
+    position: absolute;
+    left: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 44px;
+    height: 44px;
+    font-size: 44rpx;
+    color: #000;
+  }
+
+  .title {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 44px;
+    font-size: 32rpx;
+    color: transparent;
+  }
+}
 </style>