uni 背景色渐变 全屏

复制代码
<template>
    <view class="Page">
        <!-- 商城优惠券 -->
        <navBar title="优惠券" :placeholder="false" bgColor="transparent" class="fixedNav" />
        <view class="content">






        </view>
    </view>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'















onLoad((options) => {
   
})
</script>

<style scoped lang="scss">
.Page {
    min-height: 100vh;
    padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
    background: linear-gradient(to bottom,
            #c1f5fb 10%,
            #f6f6f6 25%,
            #f6f6f6 100%);
}

.fixedNav {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 999;
}

.content {
    padding-top: calc(var(--status-bar-height) + 88rpx + 30rpx);
    padding-left: 24rpx;
    padding-right: 24rpx;
}


</style>
复制代码
<template>
	<view class="nav-page">
		<up-navbar
			title=""
			:placeholder="placeholder"
			:autoBack="false"
			:fixed="fixed"
			:safeAreaInsetTop="safeAreaInsetTop"
			:border="border"
			:bgColor="bgColorComputed"
			:height="height"
			:leftIconSize="leftIconSize"
			@leftClick="leftBtn"
			@rightClick="rightClick"
		>
			<!-- 左侧插槽 -->
			<template #left>
				<slot name="left">
					<view v-if="showleft" class="nav-left" :style="{ color: color, fontSize: fontSize }">
						<up-icon name="arrow-left" :bold="true" :color="color" :size="leftIconSize" />
					</view>
				</slot>
			</template>

			<!-- 中间插槽 -->
			<template #center>
				<slot name="center">
					<text class="nav-title" :style="titleStyle">{{ title || pageTitle }}</text>
				</slot>
			</template>

			<!-- 右侧插槽 -->
			<template #right>
				<slot name="right" />
			</template>
		</up-navbar>
	</view>
</template>

<script setup lang="ts">
import { ref, computed, getCurrentInstance } from 'vue'
import { onPageScroll } from '@dcloudio/uni-app'
import { useProxy } from '@/utils/useProxy' // 假设这是你自定义的工具

// 定义 Props
const props = defineProps({
	safeAreaInsetTop: { type: Boolean, default: true },
	placeholder: { type: Boolean, default: true },
	fixed: { type: Boolean, default: true },
	border: { type: Boolean, default: false },
	autoBack: { type: Boolean, default: true },
	showleft: { type: Boolean, default: true },
	height: { type: String, default: '44px' },
	bgColor: { type: String, default: '#ffffff' },
	color: { type: String, default: '#303133' },
	fontSize: { type: String, default: '24rpx' },
	linear: { type: Boolean, default: true }, // 是否开启渐变
	leftIconSize: { type: [String, Number], default: 20 }, // 修正类型定义
	titleStyle: {
		type: Object,
		default: () => ({
			fontWeight: 'bold',
			fontSize: '32rpx',
			color: '#000000',
		})
	},
	title: { type: String, default: '' }
})

const emit = defineEmits(['leftClick', 'rightClick'])
const { proxy } = getCurrentInstance()
const bgOpacityColor = ref(props.bgColor)
const pageTitle = ref('')

// 计算最终背景色,优先使用计算后的透明度颜色
const bgColorComputed = computed(() => {
	return bgOpacityColor.value
})

// 左侧点击
const leftBtn = () => {
	if (props.autoBack) {
		// 这里保留你原本的 jumpPage 逻辑,假设 proxy 挂载了 $function
		// @ts-ignore
		proxy?.$function?.jumpPage('', null, 5)
	} else {
		emit('leftClick')
	}
}

// 右侧点击
const rightClick = () => {
	emit('rightClick')
}
function hexToRgb(hex) {
  hex = hex.replace('#', '')

  if (hex.length === 3) {
    hex = hex.split('').map(s => s + s).join('')
  }

  const bigint = parseInt(hex, 16)

  return {
    r: (bigint >> 16) & 255,
    g: (bigint >> 8) & 255,
    b: bigint & 255
  }
}
// 页面滚动处理
const handlePageScroll = (e: { scrollTop: number }) => {
	// 如果背景色不是透明,且不需要渐变,直接返回
	if (props.bgColor === 'transparent') {
		bgOpacityColor.value = props.bgColor
		return
	}

	const st = e.scrollTop
	const slideHeight = 100 // 渐变过渡的高度阈值

	// 使用 uni-app 内置 API 处理颜色,无需手动写正则
	const rgbArr = hexToRgb(props.bgColor)

	if (!rgbArr) return

	let alpha = 0
	if (st <= slideHeight) {
		alpha = st > 0 ? (st / slideHeight) : 0
	} else {
		alpha = 1
	}

	if (props.linear) {
		bgOpacityColor.value = `rgba(${rgbArr.r}, ${rgbArr.g}, ${rgbArr.b}, ${alpha.toFixed(3)})`
	} else {
		bgOpacityColor.value = props.bgColor
	}
}

// 监听页面滚动 (uni-app script setup 写法)
onPageScroll((e) => {
	handlePageScroll(e)
})

// 初始化获取页面标题
const initPageTitle = () => {
	const pages = getCurrentPages()
	const currentPage = pages[pages.length - 1]
	// 兼容 H5 和 APP 获取标题的方式
	pageTitle.value = currentPage?.meta?.navigationBar?.titleText || ''
}

// 组件挂载后
// 注意:onPageScroll 不需要在 onMounted 里注册,直接调用即可
// 这里只处理初始化逻辑
initPageTitle()
// 初始化一次背景色状态
handlePageScroll({ scrollTop: 0 })
</script>

<style lang="scss" scoped>
.nav-page {
	position: relative;
	z-index: 999;
}

:deep(.u-navbar) {
	z-index: 999999 !important;
}

.nav-left {
	display: inline-flex;
	align-items: center;
	vertical-align: middle;
}

.nav-title {
	/* 标题基础样式,会被 titleStyle 覆盖 */
}

/* 修正类名命名规范,避免使用纯标签选择器 */
.popup1 {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	transition: all 0.2s;
	height: 0;
	z-index: 999;
	overflow: hidden;

	&.on {
		height: 100vh;
	}

	.popup1-content {
		background-color: #555555;
		border-radius: 0 0 40rpx 40rpx;
		padding: 0 30rpx;
	}

	.item1 {
		font-size: 32rpx;
		color: #ffffff;
		font-weight: bold;
		margin-bottom: 40rpx;
	}

	.item2 {
		/* 必须加类名,不能直接写 > view */
		.popup-item {
			margin: 0 2% 20rpx 0;
			width: 20%;
			font-size: 24rpx;
			color: #ffffff;
			padding: 20rpx 10rpx;
			background-color: #444444;
			border-radius: 10rpx;

			

			&:nth-child(5n) {
				margin-right: 0;
			}
		}
	}
}
</style>
相关推荐
_lucas2 分钟前
做了一个glsl在线调试工具
前端·javascript·three.js
To_OC8 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
腻害兔8 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
不好听6138 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus8 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端
前端小李子9 小时前
前端环境变量裸奔?我用 EnvShield 给它穿了件防弹衣
前端
youtootech9 小时前
HarmonyOS《柚兔学伴》项目实战25-我的页面、Web 嵌入与项目总结
前端·华为·harmonyos
小林ixn10 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
醇氧11 小时前
CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单
前端·面试·职场和发展