Browse Source

修复搜索框滑动隐藏效果,实现渐进式隐藏和高度收缩

pull/1/head
Trae AI 2 months ago
parent
commit
249dc32e26
  1. 72
      pages/index/index.js
  2. 58
      pages/index/index.wxml
  3. 52
      pages/index/index.wxss

72
pages/index/index.js

@ -25,6 +25,9 @@ Page({
searchSectionVisible: true,
lastScrollTop: 0,
isScrollLocked: false,
searchSectionOpacity: 1,
searchSectionTransform: 0,
isSearchBarFullyHidden: false,
// 回到顶部按钮
showBackToTop: false,
@ -604,11 +607,13 @@ Page({
return { leftColumnGoods: leftColumn, rightColumnGoods: rightColumn }
},
// 搜索输入
// 搜索输入(实时搜索)
onSearchInput: function(e) {
this.setData({
searchKeyword: e.detail.value
})
// 实时应用筛选条件
this.searchGoods()
},
// 搜索商品
@ -637,22 +642,23 @@ Page({
})
},
// 选择地区
// 选择地区(实时更新)
selectRegion: function(e) {
const region = e.currentTarget.dataset.region
this.setData({
selectedRegion: region
})
},
// 确认地区选择
confirmRegion: function() {
// 重新显示tabBar
const app = getApp();
if (app && app.globalData) {
app.globalData.showTabBar = true;
}
// 应用筛选条件
this.setData({
selectedRegion: region,
showRegionPicker: false
})
// 重新筛选商品
const filteredGoods = this.applyFilters(this.data.goods)
const groupedGoods = this.groupGoodsForStaggeredLayout(filteredGoods)
const { leftColumnGoods, rightColumnGoods } = this.distributeToColumns(filteredGoods)
@ -660,8 +666,7 @@ Page({
filteredGoods: filteredGoods,
groupedGoods: groupedGoods,
leftColumnGoods: leftColumnGoods,
rightColumnGoods: rightColumnGoods,
showRegionPicker: false
rightColumnGoods: rightColumnGoods
})
},
@ -782,39 +787,44 @@ Page({
onScroll: function(e) {
const { scrollTop } = e.detail;
if (this.data.isScrollLocked) {
this.setData({ lastScrollTop: scrollTop });
return;
}
let searchSectionOpacity = 1;
let searchSectionTransform = 0;
let isSearchBarFullyHidden = false;
const scrollDirection = scrollTop > this.data.lastScrollTop ? 'down' : 'up';
const scrollDelta = Math.abs(scrollTop - this.data.lastScrollTop);
if (scrollTop > 50) {
// 当滚动距离超过50rpx时,开始逐渐隐藏
const hideProgress = Math.min((scrollTop - 50) / 100, 1); // 0-1的隐藏进度
searchSectionOpacity = 1 - hideProgress;
searchSectionTransform = -20 * hideProgress;
if (scrollDelta < 10) {
this.setData({ lastScrollTop: scrollTop });
return;
// 当隐藏进度达到100%时,完全隐藏并收缩高度
if (hideProgress >= 1) {
isSearchBarFullyHidden = true;
}
}
if (scrollDirection === 'down' && scrollTop > 100 && this.data.searchSectionVisible) {
this.setData({ searchSectionVisible: false, isScrollLocked: true });
setTimeout(() => {
this.setData({ isScrollLocked: false });
}, 300);
} else if (scrollDirection === 'up' && !this.data.searchSectionVisible && scrollTop < 50) {
this.setData({ searchSectionVisible: true, isScrollLocked: true });
setTimeout(() => {
this.setData({ isScrollLocked: false });
}, 300);
// 当滚动回到顶部时,重置所有状态
if (scrollTop <= 50) {
searchSectionOpacity = 1;
searchSectionTransform = 0;
isSearchBarFullyHidden = false;
}
// 更新搜索框状态和样式
this.setData({
searchSectionOpacity: searchSectionOpacity,
searchSectionTransform: searchSectionTransform,
isSearchBarFullyHidden: isSearchBarFullyHidden,
lastScrollTop: scrollTop
});
// 回到顶部按钮显示逻辑
if (scrollTop > 300 && !this.data.showBackToTop) {
this.setData({ showBackToTop: true });
} else if (scrollTop <= 300 && this.data.showBackToTop) {
this.setData({ showBackToTop: false });
}
this.setData({ lastScrollTop: scrollTop });
const { scrollHeight, clientHeight } = e.detail;
const distanceToBottom = scrollHeight - scrollTop - clientHeight;

58
pages/index/index.wxml

@ -1,27 +1,33 @@
<view class="container">
<!-- 标题 -->
<view class="title {{searchSectionVisible ? '' : 'title-hidden'}}">专业的鸡蛋现货交易平台</view>
<!-- 顶部搜索区域容器 -->
<view
class="top-section {{isSearchBarFullyHidden ? 'top-hidden' : ''}}"
style="opacity: {{searchSectionOpacity}}; transform: translateY({{searchSectionTransform}}rpx);"
>
<!-- 标题 -->
<view class="title">专业的鸡蛋现货交易平台</view>
<!-- 搜索区域 -->
<view class="search-section {{searchSectionVisible ? 'search-visible' : 'search-hidden'}}">
<view class="search-bar">
<view class="search-input-wrapper">
<!-- 将地区选择器放在最左边 -->
<view class="region-selector" bindtap="toggleRegionPicker">
<text>{{selectedRegion || '全国'}}</text>
<text class="region-arrow">▼</text>
<!-- 搜索区域 -->
<view class="search-section">
<view class="search-bar">
<view class="search-input-wrapper">
<!-- 将地区选择器放在最左边 -->
<view class="region-selector" bindtap="toggleRegionPicker">
<text>{{selectedRegion || '全国'}}</text>
<text class="region-arrow">▼</text>
</view>
<!-- 搜索图标和输入框 -->
<text class="search-icon">🔍</text>
<input
class="search-input"
placeholder="搜索商品名称或地区"
placeholder-class="search-placeholder"
value="{{searchKeyword}}"
bindinput="onSearchInput"
/>
</view>
<!-- 搜索图标和输入框 -->
<text class="search-icon">🔍</text>
<input
class="search-input"
placeholder="搜索商品名称或地区"
placeholder-class="search-placeholder"
value="{{searchKeyword}}"
bindinput="onSearchInput"
/>
<button class="search-button" bindtap="searchGoods">搜索</button>
</view>
<button class="search-button" bindtap="searchGoods">搜索</button>
</view>
</view>
@ -40,7 +46,6 @@
{{item}}
</view>
</view>
<button class="confirm-region-btn" bindtap="confirmRegion">确定</button>
</view>
</view>
@ -195,6 +200,13 @@
</view>
</view>
<!-- 无搜索结果提示 -->
<view wx:if="{{filteredGoods.length === 0 && !isLoading}}" class="empty-goods">
<text class="empty-icon">🔍</text>
<text class="empty-text">暂无相关商品</text>
<text class="empty-hint">试试调整搜索条件或地区筛选</text>
</view>
<!-- 正常商品列表 -->
<view
class="waterfall-item"
@ -202,7 +214,7 @@
wx:key="id"
data-item="{{item}}"
bindtap="viewGoodsDetail"
wx:if="{{!item.isAd}}"
wx:if="{{!item.isAd && filteredGoods.length > 0}}"
>
<view class="product-card">
<view class="product-image-wrapper">
@ -260,7 +272,7 @@
wx:key="id"
data-item="{{item}}"
bindtap="viewGoodsDetail"
wx:if="{{!item.isAd}}"
wx:if="{{!item.isAd && filteredGoods.length > 0}}"
>
<view class="product-card">
<view class="product-image-wrapper">

52
pages/index/index.wxss

@ -19,50 +19,38 @@ page {
background-color: #f8f8f8;
}
/* 标题样式 */
.title {
font-size: 36rpx;
font-weight: bold;
margin: 20rpx;
color: #333;
text-align: center;
/* 顶部搜索区域容器 */
.top-section {
flex-shrink: 0;
transition: all 0.3s ease;
padding: 10rpx 0;
margin-bottom: 20rpx;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
will-change: opacity, transform, padding, margin, max-height;
}
.title-hidden {
opacity: 0;
transform: translateY(-20rpx);
height: 0;
margin: 0;
/* 顶部搜索区域完全隐藏状态 - 用于收缩高度 */
.top-hidden {
max-height: 0;
padding: 0;
overflow: hidden;
margin-bottom: 0;
pointer-events: none;
}
/* 搜索区域样式 */
.search-section {
/* 标题样式 */
.title {
font-size: 36rpx;
font-weight: bold;
margin: 10rpx 20rpx;
color: #333;
text-align: center;
flex-shrink: 0;
transition: all 0.3s ease;
}
.search-visible {
opacity: 1;
transform: translateY(0);
height: auto;
}
.search-hidden {
opacity: 0;
transform: translateY(-100%);
height: 0;
overflow: hidden;
}
/* 搜索区域样式 */
.search-section {
width: 100%;
margin: 0 20rpx 20rpx 20rpx;
flex: 0 1 auto;
margin: 0 30rpx 0 10rpx;
box-sizing: border-box;
}

Loading…
Cancel
Save