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"
/>
相关推荐
用户921080262862 分钟前
Bubble 消息操作区改造:复制、重新生成和反馈
前端
LEE6 分钟前
AI Agent 都在疯狂加功能,它说:我全砍了
前端·后端
张清悠6 分钟前
用 TRAE Work 把 PRD + 设计稿注释,整理成 20 分钟可排期前端任务清单
前端
Brown.alexis1 小时前
es6知识点5-自备使用
前端·javascript·es6
杨利杰YJlio1 小时前
KB5121003更新详解:安全启动证书、AI组件、资源管理器与安装验证
前端·javascript·后端
紫菜猫一只2 小时前
Vue 3 与 React 常用写法对比
前端
jinggongszh2 小时前
使用AI协同开发产品条码规则功能——从“理解方案、原型、接口文档”到“落地真实前端代码”
前端·人工智能·mes系统·mes工程架构
渔夫正在掘金2 小时前
Cordis 中文教程:渐进式构建插件化应用
前端·node.js·ai编程
打呵欠的猫2 小时前
前端团队 3 个月 AI 实践复盘:哪些场景 ROI 最高,哪些是伪需求
前端·ai编程
gyx_这个杀手不太冷静2 小时前
高级前端开发职业规划(2026—2035)
前端·面试·agent