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"
/>
相关推荐
一起养小猫2 小时前
Flutter for OpenHarmony 实战:科学计算器完整开发指南
android·前端·flutter·游戏·harmonyos
Jinuss2 小时前
源码分析之React中Scheduler调度器的任务优先级
前端·react.js·前端框架
波波0072 小时前
每日一题:在 .NET 中遍历集合(如 List<T>、数组、字典)的过程中进行增删改查会不会有影响?可能引发哪些问题?实际开发中应如何避免?
前端·list
念念不忘 必有回响2 小时前
码云流水线前端资源传输至目标服务器
运维·服务器·前端
我是伪码农2 小时前
Vue 2.2
前端·javascript·vue.js
●VON2 小时前
React Native for OpenHarmony:深入剖析 Switch 组件的状态绑定、无障碍与样式定制
javascript·学习·react native·react.js·von
时光追逐者2 小时前
一个基于 .NET + Vue 实现的通用权限管理平台(RBAC模式),前后端分离模式,开箱即用!
前端·vue.js·c#·.net·.net core
Aotman_2 小时前
Vue el-table 表尾合计行
前端·javascript·vue.js·elementui·前端框架·ecmascript
编程猪猪侠2 小时前
Vue3 + Ant Design Vue 实现 Table 表格嵌套 Radio 单选框
javascript·vue.js·anti-design-vue