uniApp下拉渐变头部 拿来即用

组件封装还是不完全 少一些自动化的东西 希望有大佬可以指点下

javascript 复制代码
<script lang="ts" setup>
import { computed } from 'vue'

const props = defineProps<{
  // 主题色
  themeColor?: string
  // 渐变起始透明度
  startOpacity?: number
  // 渐变结束透明度
  endOpacity?: number
  // 触发完全渐变的滚动距离
  threshold?: number
  // 是否显示标题
  showTitle?: boolean
  // 标题文本
  title?: string
  // 滚动距离(从父组件传入)
  scrollTop?: number
  // 是否显示返回按钮
  isToBack?: boolean
  // 是否显示返回主页按钮
  isToHome?: boolean
  // 是否显示右侧按钮
  isToRightBack?: boolean
}>()

const emit = defineEmits<{
  (e: 'back'): void
  (e: 'rightClick'): void
}>()

// 默认值
const defaultThemeColor = '#1e88e5' // 蓝色主题色
const defaultStartOpacity = 0
const defaultEndOpacity = 1
const defaultThreshold = 100

// 当前透明度
const opacity = computed(() => {
  const scrollTopVal = props.scrollTop || 0
  const threshold = props.threshold || defaultThreshold
  const startOpacity = props.startOpacity || defaultStartOpacity
  const endOpacity = props.endOpacity || defaultEndOpacity

  // 计算透明度,从startOpacity到endOpacity渐变
  const opacityRange = endOpacity - startOpacity
  const scrollProgress = Math.min(scrollTopVal / threshold, 1)

  return startOpacity + (opacityRange * scrollProgress)
})

// 计算当前背景色
const bgColor = computed(() => {
  const color = props.themeColor || defaultThemeColor
  const currentOpacity = opacity.value
  // 将16进制颜色转换为rgba
  const hex = color.replace('#', '')
  const r = Number.parseInt(hex.substring(0, 2), 16)
  const g = Number.parseInt(hex.substring(2, 4), 16)
  const b = Number.parseInt(hex.substring(4, 6), 16)

  return `rgba(${r}, ${g}, ${b}, ${currentOpacity})`
})

// 计算文字颜色
const textColor = computed(() => {
  return opacity.value > 0.5 ? '#ffffff' : '#000000'
})

// 处理返回按钮点击
function handleBack() {
  emit('back')
}
// 处理返回主页点击
function handleBackHome() {
  emit('backHome')
}

// 处理右侧按钮点击
function handleRightClick() {
  emit('rightClick')
}
</script>

<template>
  <view class="gradient-header" :style="{ backgroundColor: bgColor }">
    <view class="header-content flex items-center justify-between px-4">
      <!-- 左侧返回按钮 -->
      <view v-if="isToBack" class="header-left" @click="handleBack">
        <text class="text-lg" :style="{ color: textColor }">
          <uv-icon name="arrow-left" />
        </text>
      </view>
      <!-- 返回主页 -->
      <view v-if="isToHome" class="header-left header-left-home" @click="handleBackHome">
        <text class="text-lg" :style="{ color: textColor }">
          <uv-icon name="home" />
        </text>
      </view>

      <!-- 中间标题 -->
      <view v-if="showTitle" class="header-center flex-1 text-center" :style="{ color: textColor }">
        {{ title || '' }}
      </view>
      <view v-else class="header-center flex-1" />

      <!-- 右侧按钮 -->
      <view v-if="isToRightBack" class="header-right" @click="handleRightClick">
        <text class="text-lg" :style="{ color: textColor }">···</text>
      </view>
    </view>
  </view>
</template>

<style scoped>
.gradient-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 88rpx;
  z-index: 999;
  transition: background-color 0.3s ease;
}

.header-content {
  height: 100%;
  line-height: 100%;
}
.header-left {
  position: absolute;
  top: 50%;
  left: 30rpx;
  transform: translateY(-50%);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  border: 2rpx solid rgba(0, 0, 0, 0.2);
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.header-left-home {
  position: absolute;
  top: 50%;
  left: 100rpx;
  transform: translateY(-50%);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  border: 2rpx solid rgba(0, 0, 0, 0.2);
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
复制代码
import GradientHeader from '@/components/GradientHeader.vue'

// 滚动距离
const scrollTop = ref(0)

// 处理页面滚动事件(uni-app 生命周期函数)
onPageScroll((e: any) => {
  scrollTop.value = e?.scrollTop || 0
})
  
<!-- 渐变头部 -->
<GradientHeader
  theme-color="#6283d4" :start-opacity="0" :end-opacity="1" :threshold="100" :show-title="true"
  title="首页" :scroll-top="scrollTop" :is-to-back="false" :is-to-right-back="false" @back="handleBack"
  @right-click="handleRightClick"
/>
相关推荐
小鹏linux5 小时前
Ubuntu 22.04 部署开源免费具有精美现代web页面的Casdoor账号管理系统
linux·前端·ubuntu·开源·堡垒机
前端若水6 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
Bigger6 小时前
mini-cc:一个轻量级 AI 编程助手的诞生
前端·ai编程·claude
涵涵(互关)6 小时前
Naive-ui树型选择器只显示根节点
前端·ui·vue
BY组态6 小时前
Ricon组态系统最佳实践:从零开始构建物联网监控平台
前端·物联网·iot·web组态·组态
BY组态6 小时前
Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
前端·物联网·iot·web组态·组态
SoaringHeart6 小时前
Flutter进阶:OverlayEntry 插入图层管理器 NOverlayZIndexManager
前端·flutter
放下华子我只抽RuiKe56 小时前
React 从入门到生产(四):自定义 Hook
前端·javascript·人工智能·深度学习·react.js·自然语言处理·前端框架
XinZong7 小时前
OpenClaw 实现双重心跳(Heartbeat)+ clawreach虾聊项目实现
javascript
IT_陈寒8 小时前
Redis缓存击穿把我整不会了,原来还有这手操作
前端·人工智能·后端