Commit 4f00d7595c578dbd30c86913a13f65eb16ee99ac
1 parent
844ae2b7
优化个人中心页面:实现玻璃态卡片效果、3D悬浮动效和流动导航指示器
- 增强玻璃态卡片效果:半透明背景+模糊效果+精致边框+内层高光 - 添加3D悬浮动效:所有卡片支持点击缩放和阴影变化,光晕扫过动画 - 优化底部导航栏:胶囊式设计+流动选中指示器,平滑过渡动画 - 提升整体视觉体验:轻盈高级的玻璃质感,流畅的交互动效
Showing
2 changed files
with
167 additions
and
21 deletions
绿纤uni-app/components/custom-tab-bar/index.vue
| 1 | <template> | 1 | <template> |
| 2 | <view class="tab-block"> | 2 | <view class="tab-block"> |
| 3 | <view class='tab-list flex flex-center' :class="showMiddleButton === true?'tab-list-middle':'tab-list-default'"> | 3 | <view class='tab-list flex flex-center' :class="showMiddleButton === true?'tab-list-middle':'tab-list-default'"> |
| 4 | + <!-- 流动选中指示器 --> | ||
| 5 | + <view class="tab-indicator" :style="{ left: indicatorLeft + 'px', width: indicatorWidth + 'px' }"></view> | ||
| 4 | <view v-for="(item, index) in tabList" | 6 | <view v-for="(item, index) in tabList" |
| 5 | :class="'list-item flex flex-column flex-middle ' + item.middleClass" | 7 | :class="'list-item flex flex-column flex-middle ' + item.middleClass" |
| 6 | @tap="handlePush(item, index)" | 8 | @tap="handlePush(item, index)" |
| 7 | - :key="index"> | 9 | + :key="index" |
| 10 | + :ref="'tabItem' + index"> | ||
| 8 | <view class="item-img-box"> | 11 | <view class="item-img-box"> |
| 9 | <image | 12 | <image |
| 10 | class="item-img" | 13 | class="item-img" |
| @@ -84,7 +87,42 @@ | @@ -84,7 +87,42 @@ | ||
| 84 | return matchedIndex >= 0 ? matchedIndex : 0; | 87 | return matchedIndex >= 0 ? matchedIndex : 0; |
| 85 | } | 88 | } |
| 86 | }, | 89 | }, |
| 90 | + mounted() { | ||
| 91 | + this.updateIndicator() | ||
| 92 | + }, | ||
| 93 | + watch: { | ||
| 94 | + currentTabIndex() { | ||
| 95 | + this.$nextTick(() => { | ||
| 96 | + setTimeout(() => { | ||
| 97 | + this.updateIndicator() | ||
| 98 | + }, 100) | ||
| 99 | + }) | ||
| 100 | + } | ||
| 101 | + }, | ||
| 87 | methods: { | 102 | methods: { |
| 103 | + // 更新流动指示器位置 | ||
| 104 | + updateIndicator() { | ||
| 105 | + this.$nextTick(() => { | ||
| 106 | + try { | ||
| 107 | + const query = uni.createSelectorQuery().in(this) | ||
| 108 | + query.select('.tab-list').boundingClientRect((tabListRect) => { | ||
| 109 | + query.selectAll('.list-item').boundingClientRect((rects) => { | ||
| 110 | + if (rects && rects.length > 0 && this.currentTabIndex >= 0 && this.currentTabIndex < rects.length) { | ||
| 111 | + const currentRect = rects[this.currentTabIndex] | ||
| 112 | + | ||
| 113 | + if (currentRect && tabListRect) { | ||
| 114 | + // 计算指示器的位置和宽度 | ||
| 115 | + this.indicatorWidth = currentRect.width * 0.6 | ||
| 116 | + this.indicatorLeft = currentRect.left - tabListRect.left + (currentRect.width - this.indicatorWidth) / 2 | ||
| 117 | + } | ||
| 118 | + } | ||
| 119 | + }).exec() | ||
| 120 | + }).exec() | ||
| 121 | + } catch (e) { | ||
| 122 | + console.error('更新指示器失败:', e) | ||
| 123 | + } | ||
| 124 | + }) | ||
| 125 | + }, | ||
| 88 | // 点击按钮 | 126 | // 点击按钮 |
| 89 | handlePush(item, index) { | 127 | handlePush(item, index) { |
| 90 | if (this.currentTabIndex !== index) { | 128 | if (this.currentTabIndex !== index) { |
| @@ -134,29 +172,60 @@ | @@ -134,29 +172,60 @@ | ||
| 134 | .tab-list{ | 172 | .tab-list{ |
| 135 | height: 120rpx; | 173 | height: 120rpx; |
| 136 | } | 174 | } |
| 137 | - .tab-list-default{ | ||
| 138 | - background-color: rgba(255, 255, 255, 0.85); | ||
| 139 | - border-radius: 28rpx; | ||
| 140 | - box-shadow: 0rpx 4rpx 20rpx rgba(0, 0, 0, 0.1); | ||
| 141 | - backdrop-filter: blur(10rpx); | ||
| 142 | - } | 175 | + .tab-list-default{ |
| 176 | + background: rgba(255, 255, 255, 0.7); | ||
| 177 | + backdrop-filter: blur(20px) saturate(180%); | ||
| 178 | + -webkit-backdrop-filter: blur(20px) saturate(180%); | ||
| 179 | + border-radius: 28rpx; | ||
| 180 | + box-shadow: 0rpx 8rpx 32rpx rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(255, 255, 255, 0.3) inset; | ||
| 181 | + border: 1px solid rgba(255, 255, 255, 0.4); | ||
| 182 | + position: relative; | ||
| 183 | + transition: all 0.3s ease; | ||
| 184 | + } | ||
| 143 | .tab-list-middle { | 185 | .tab-list-middle { |
| 144 | position: relative; | 186 | position: relative; |
| 145 | background: url('https://res.paquapp.com/popmartvip/home/nav_bar_bg_2x.png') no-repeat center center; | 187 | background: url('https://res.paquapp.com/popmartvip/home/nav_bar_bg_2x.png') no-repeat center center; |
| 146 | background-size: cover; | 188 | background-size: cover; |
| 147 | } | 189 | } |
| 190 | + /* 流动选中指示器 */ | ||
| 191 | + .tab-indicator { | ||
| 192 | + position: absolute; | ||
| 193 | + bottom: 8rpx; | ||
| 194 | + height: 4rpx; | ||
| 195 | + background: linear-gradient(90deg, #43a047 0%, #66bb6a 100%); | ||
| 196 | + border-radius: 2rpx; | ||
| 197 | + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | ||
| 198 | + box-shadow: 0 2rpx 8rpx rgba(67, 160, 71, 0.4); | ||
| 199 | + z-index: 1; | ||
| 200 | + } | ||
| 201 | + | ||
| 148 | .list-item { | 202 | .list-item { |
| 149 | flex: 1; | 203 | flex: 1; |
| 204 | + position: relative; | ||
| 205 | + z-index: 2; | ||
| 206 | + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | ||
| 207 | + | ||
| 150 | .item-img-box { | 208 | .item-img-box { |
| 151 | width: 40rpx; | 209 | width: 40rpx; |
| 152 | height: 40rpx; | 210 | height: 40rpx; |
| 153 | margin-bottom: 6rpx; | 211 | margin-bottom: 6rpx; |
| 154 | position: relative; | 212 | position: relative; |
| 213 | + transition: transform 0.3s ease; | ||
| 155 | } | 214 | } |
| 156 | 215 | ||
| 157 | .item-img { | 216 | .item-img { |
| 158 | width: 40rpx; | 217 | width: 40rpx; |
| 159 | height: 40rpx; | 218 | height: 40rpx; |
| 219 | + transition: transform 0.3s ease; | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | + /* 3D悬浮动效 */ | ||
| 223 | + &:active { | ||
| 224 | + transform: translateY(-2rpx) scale(0.95); | ||
| 225 | + | ||
| 226 | + .item-img-box { | ||
| 227 | + transform: scale(1.1); | ||
| 228 | + } | ||
| 160 | } | 229 | } |
| 161 | } | 230 | } |
| 162 | 231 |
绿纤uni-app/pages/me/me.vue
| @@ -691,14 +691,40 @@ export default { | @@ -691,14 +691,40 @@ export default { | ||
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | .warpboxss { | 693 | .warpboxss { |
| 694 | - background-color: rgba(255, 255, 255, 0.4); | ||
| 695 | - backdrop-filter: blur(16px) saturate(180%); | ||
| 696 | - -webkit-backdrop-filter: blur(16px) saturate(180%); | 694 | + background: rgba(255, 255, 255, 0.25); |
| 695 | + backdrop-filter: blur(20px) saturate(180%); | ||
| 696 | + -webkit-backdrop-filter: blur(20px) saturate(180%); | ||
| 697 | padding: 30rpx; | 697 | padding: 30rpx; |
| 698 | border-radius: 24rpx; | 698 | border-radius: 24rpx; |
| 699 | - box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08); | ||
| 700 | - border: 1px solid rgba(255, 255, 255, 0.125); | 699 | + box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(255, 255, 255, 0.3) inset; |
| 700 | + border: 1px solid rgba(255, 255, 255, 0.4); | ||
| 701 | margin-bottom: 24rpx; | 701 | margin-bottom: 24rpx; |
| 702 | + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | ||
| 703 | + transform: translateY(0) scale(1); | ||
| 704 | + position: relative; | ||
| 705 | + overflow: hidden; | ||
| 706 | +} | ||
| 707 | + | ||
| 708 | +/* 3D悬浮动效 - 所有卡片 */ | ||
| 709 | +.warpboxss::before { | ||
| 710 | + content: ''; | ||
| 711 | + position: absolute; | ||
| 712 | + top: 0; | ||
| 713 | + left: -100%; | ||
| 714 | + width: 100%; | ||
| 715 | + height: 100%; | ||
| 716 | + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); | ||
| 717 | + transition: left 0.6s ease; | ||
| 718 | +} | ||
| 719 | + | ||
| 720 | +.warpboxss:active { | ||
| 721 | + transform: translateY(-4rpx) scale(0.98); | ||
| 722 | + box-shadow: 0 12rpx 48rpx rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(255, 255, 255, 0.4) inset; | ||
| 723 | + border-color: rgba(255, 255, 255, 0.5); | ||
| 724 | +} | ||
| 725 | + | ||
| 726 | +.warpboxss:active::before { | ||
| 727 | + left: 100%; | ||
| 702 | } | 728 | } |
| 703 | 729 | ||
| 704 | .warpboxs-small-title { | 730 | .warpboxs-small-title { |
| @@ -847,12 +873,17 @@ export default { | @@ -847,12 +873,17 @@ export default { | ||
| 847 | } | 873 | } |
| 848 | 874 | ||
| 849 | .kpi-card { | 875 | .kpi-card { |
| 850 | - background: linear-gradient(135deg, #4caf50 0%, #66bb6a 100%); | 876 | + background: linear-gradient(135deg, rgba(76, 175, 80, 0.85) 0%, rgba(102, 187, 106, 0.85) 100%); |
| 877 | + backdrop-filter: blur(20px) saturate(180%); | ||
| 878 | + -webkit-backdrop-filter: blur(20px) saturate(180%); | ||
| 851 | border-radius: 24rpx; | 879 | border-radius: 24rpx; |
| 852 | padding: 40rpx 30rpx; | 880 | padding: 40rpx 30rpx; |
| 853 | - box-shadow: 0 8rpx 24rpx rgba(76, 175, 80, 0.3); | 881 | + box-shadow: 0 8rpx 32rpx rgba(76, 175, 80, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.2) inset; |
| 882 | + border: 1px solid rgba(255, 255, 255, 0.3); | ||
| 854 | position: relative; | 883 | position: relative; |
| 855 | overflow: hidden; | 884 | overflow: hidden; |
| 885 | + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | ||
| 886 | + transform: translateY(0) scale(1); | ||
| 856 | 887 | ||
| 857 | &::before { | 888 | &::before { |
| 858 | content: ''; | 889 | content: ''; |
| @@ -861,13 +892,25 @@ export default { | @@ -861,13 +892,25 @@ export default { | ||
| 861 | right: -50%; | 892 | right: -50%; |
| 862 | width: 200%; | 893 | width: 200%; |
| 863 | height: 200%; | 894 | height: 200%; |
| 864 | - background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%); | 895 | + background: radial-gradient(circle, rgba(255, 255, 255, 0.15) 0%, transparent 70%); |
| 896 | + transition: transform 0.6s ease; | ||
| 897 | + } | ||
| 898 | + | ||
| 899 | + &:active { | ||
| 900 | + transform: translateY(-6rpx) scale(0.97); | ||
| 901 | + box-shadow: 0 16rpx 48rpx rgba(76, 175, 80, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.3) inset; | ||
| 902 | + } | ||
| 903 | + | ||
| 904 | + &:active::before { | ||
| 905 | + transform: rotate(180deg); | ||
| 865 | } | 906 | } |
| 866 | 907 | ||
| 867 | .kpi-title { | 908 | .kpi-title { |
| 868 | font-size: 26rpx; | 909 | font-size: 26rpx; |
| 869 | - color: rgba(255, 255, 255, 0.9); | 910 | + color: rgba(255, 255, 255, 0.95); |
| 870 | margin-bottom: 16rpx; | 911 | margin-bottom: 16rpx; |
| 912 | + position: relative; | ||
| 913 | + z-index: 1; | ||
| 871 | } | 914 | } |
| 872 | 915 | ||
| 873 | .kpi-value { | 916 | .kpi-value { |
| @@ -875,6 +918,8 @@ export default { | @@ -875,6 +918,8 @@ export default { | ||
| 875 | font-weight: 700; | 918 | font-weight: 700; |
| 876 | color: #ffffff; | 919 | color: #ffffff; |
| 877 | line-height: 1.2; | 920 | line-height: 1.2; |
| 921 | + position: relative; | ||
| 922 | + z-index: 1; | ||
| 878 | } | 923 | } |
| 879 | } | 924 | } |
| 880 | 925 | ||
| @@ -895,6 +940,13 @@ export default { | @@ -895,6 +940,13 @@ export default { | ||
| 895 | flex-direction: column; | 940 | flex-direction: column; |
| 896 | align-items: center; | 941 | align-items: center; |
| 897 | text-align: center; | 942 | text-align: center; |
| 943 | + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | ||
| 944 | + transform: translateY(0) scale(1); | ||
| 945 | + cursor: pointer; | ||
| 946 | + } | ||
| 947 | + | ||
| 948 | + .small-stat-item:active { | ||
| 949 | + transform: translateY(-4rpx) scale(0.95); | ||
| 898 | } | 950 | } |
| 899 | 951 | ||
| 900 | .small-stat-icon { | 952 | .small-stat-icon { |
| @@ -951,13 +1003,38 @@ export default { | @@ -951,13 +1003,38 @@ export default { | ||
| 951 | } | 1003 | } |
| 952 | 1004 | ||
| 953 | .data-card { | 1005 | .data-card { |
| 954 | - background-color: rgba(255, 255, 255, 0.4); | ||
| 955 | - backdrop-filter: blur(16px) saturate(180%); | ||
| 956 | - -webkit-backdrop-filter: blur(16px) saturate(180%); | 1006 | + background: rgba(255, 255, 255, 0.25); |
| 1007 | + backdrop-filter: blur(20px) saturate(180%); | ||
| 1008 | + -webkit-backdrop-filter: blur(20px) saturate(180%); | ||
| 957 | border-radius: 24rpx; | 1009 | border-radius: 24rpx; |
| 958 | padding: 30rpx; | 1010 | padding: 30rpx; |
| 959 | - box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08); | ||
| 960 | - border: 1px solid rgba(255, 255, 255, 0.125); | 1011 | + box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(255, 255, 255, 0.3) inset; |
| 1012 | + border: 1px solid rgba(255, 255, 255, 0.4); | ||
| 1013 | + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | ||
| 1014 | + transform: translateY(0) scale(1); | ||
| 1015 | + position: relative; | ||
| 1016 | + overflow: hidden; | ||
| 1017 | +} | ||
| 1018 | + | ||
| 1019 | +.data-card::before { | ||
| 1020 | + content: ''; | ||
| 1021 | + position: absolute; | ||
| 1022 | + top: 0; | ||
| 1023 | + left: -100%; | ||
| 1024 | + width: 100%; | ||
| 1025 | + height: 100%; | ||
| 1026 | + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); | ||
| 1027 | + transition: left 0.6s ease; | ||
| 1028 | +} | ||
| 1029 | + | ||
| 1030 | +.data-card:active { | ||
| 1031 | + transform: translateY(-4rpx) scale(0.98); | ||
| 1032 | + box-shadow: 0 12rpx 48rpx rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(255, 255, 255, 0.4) inset; | ||
| 1033 | + border-color: rgba(255, 255, 255, 0.5); | ||
| 1034 | +} | ||
| 1035 | + | ||
| 1036 | +.data-card:active::before { | ||
| 1037 | + left: 100%; | ||
| 961 | } | 1038 | } |
| 962 | 1039 | ||
| 963 | .data-card-title { | 1040 | .data-card-title { |