177 lines
3.1 KiB
Vue
177 lines
3.1 KiB
Vue
<template>
|
||
<view class="page">
|
||
|
||
<!-- 顶部折叠头部 -->
|
||
<view
|
||
class="header"
|
||
:style="{ height: headerHeight + 'px' }"
|
||
>
|
||
|
||
<!-- 背景 -->
|
||
<view class="header-bg"></view>
|
||
|
||
<!-- 内容层 -->
|
||
<view
|
||
class="header-content"
|
||
:style="{
|
||
transform: `translateY(${contentY}px)`
|
||
}"
|
||
>
|
||
|
||
<!-- 头像(单独动画) -->
|
||
<image
|
||
class="avatar"
|
||
src="/static/avatar.png"
|
||
:style="{
|
||
transform: `scale(${avatarScale}) translateY(${avatarY}px)`
|
||
}"
|
||
/>
|
||
|
||
<!-- 文本 -->
|
||
<view class="info">
|
||
<view class="name">张三</view>
|
||
<view class="desc">iOS通讯录详情页</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<!-- 内容(重点:不会被遮挡) -->
|
||
<view class="content">
|
||
<view class="card" v-for="i in 30" :key="i">
|
||
详情内容 {{ i }}
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
scrollY: 0,
|
||
|
||
headerMax: 260,
|
||
headerMin: 90,
|
||
|
||
avatarScale: 1,
|
||
avatarY: 0,
|
||
contentY: 0
|
||
};
|
||
},
|
||
|
||
computed: {
|
||
headerHeight() {
|
||
const y = this.scrollY;
|
||
|
||
// 🔥 折叠高度(关键)
|
||
return Math.max(this.headerMin, this.headerMax - y);
|
||
}
|
||
},
|
||
|
||
onPageScroll(e) {
|
||
const y = e.scrollTop;
|
||
this.scrollY = y;
|
||
|
||
// =========================
|
||
// 1. 进度(0~1)
|
||
// =========================
|
||
const max = 160;
|
||
let p = Math.min(y / max, 1);
|
||
|
||
// =========================
|
||
// 2. 头像缩小(只影响头像)
|
||
// =========================
|
||
this.avatarScale = 1 - p * 0.4; // 1 → 0.6
|
||
|
||
// =========================
|
||
// 3. 头像上移(贴近顶部)
|
||
// =========================
|
||
this.avatarY = -p * 20;
|
||
|
||
// =========================
|
||
// 4. 内容层轻微上移
|
||
// =========================
|
||
this.contentY = -p * 10;
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.page {
|
||
background: #f5f6f7;
|
||
}
|
||
|
||
/* =====================
|
||
header(核心)
|
||
===================== */
|
||
.header {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
overflow: hidden;
|
||
z-index: 10;
|
||
}
|
||
|
||
/* 背景 */
|
||
.header-bg {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(180deg, #3b82f6, #1e40af);
|
||
}
|
||
|
||
/* 内容区 */
|
||
.header-content {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
left: 30px;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
/* 头像 */
|
||
.avatar {
|
||
width: 140rpx;
|
||
height: 140rpx;
|
||
border-radius: 50%;
|
||
margin-right: 20rpx;
|
||
border: 4rpx solid rgba(255,255,255,0.6);
|
||
transform-origin: center;
|
||
}
|
||
|
||
/* 文本 */
|
||
.info {
|
||
color: #fff;
|
||
}
|
||
|
||
.name {
|
||
font-size: 40rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.desc {
|
||
font-size: 24rpx;
|
||
opacity: 0.85;
|
||
margin-top: 6rpx;
|
||
}
|
||
|
||
/* =====================
|
||
内容(关键:防遮挡)
|
||
===================== */
|
||
.content {
|
||
padding-top: 260px; /* ⭐ 解决你说的遮挡问题 */
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.card {
|
||
background: #fff;
|
||
margin-bottom: 20rpx;
|
||
padding: 30rpx;
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 10rpx 30rpx rgba(0,0,0,0.05);
|
||
}
|
||
</style> |