scroll-sticky.uvue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <template>
  2. <scroll-view ref="scroll" @scroll="onScroll" class="page" bounces="false">
  3. <view class="content-item">
  4. <text class="text">向上滑动页面,体验元素吸顶效果。</text>
  5. </view>
  6. <view v-for="(item,index) in list" :key="index" class="content-item">
  7. <text class="text">first content-{{item}}</text>
  8. </view>
  9. <view ref="sticky" class="search">
  10. <view style="flex-direction: row;">
  11. <image src="/static/template/scroll-fold-nav/search.png" style="width: 15px;" mode="widthFix"></image>
  12. <text class="search-tip-text">请输入你要搜索的内容</text>
  13. </view>
  14. <text class="search-btn">搜索</text>
  15. </view>
  16. <view v-for="(item,index) in list" :key="index" class="content-item">
  17. <text class="text">second content-{{item}}</text>
  18. </view>
  19. <view v-for="(item,index) in list" :key="index" class="content-item">
  20. <text class="text">second content-{{item}}</text>
  21. </view>
  22. </scroll-view>
  23. </template>
  24. <script>
  25. export default {
  26. data() {
  27. return {
  28. list: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'],
  29. stickyTop: 0,
  30. stickyTran: 0,
  31. scrollTop: 0,
  32. stickyNode: null as UniElement | null
  33. }
  34. },
  35. methods: {
  36. onScroll(e : ScrollEvent) {
  37. if (e.detail.scrollTop > this.stickyTop) {
  38. let stickyTran = e.detail.scrollTop - this.stickyTop;
  39. if (stickyTran != this.stickyTran) {
  40. this.stickyNode?.style?.setProperty('transform', 'translateY(' + stickyTran + 'px)');
  41. }
  42. this.stickyTran = stickyTran;
  43. } else {
  44. this.stickyNode?.style?.setProperty('transform', '');
  45. this.stickyTran = 0;
  46. }
  47. },
  48. back() {
  49. uni.navigateBack({
  50. success(result) {
  51. console.log('navigateBack success', result.errMsg)
  52. },
  53. fail(error) {
  54. console.log('navigateBack fail', error.errMsg)
  55. },
  56. complete(result) {
  57. console.log('navigateBack complete', result.errMsg)
  58. },
  59. })
  60. },
  61. async calcStickyTop() {
  62. this.stickyNode = this.$refs['sticky'] as UniElement;
  63. // let rect = this.stickyNode?.getBoundingClientRect();
  64. // this.stickyTop = rect?.top;
  65. //this.stickyTop = this.stickyNode?.getBoundingClientRect()?.top;
  66. const stickyRect = await (this.$refs['sticky'] as UniElement).getBoundingClientRectAsync()!;
  67. const scrollRect = await (this.$refs['scroll'] as UniElement).getBoundingClientRectAsync()!;
  68. this.stickyTop = stickyRect.top - scrollRect.top;
  69. console.log(stickyRect, scrollRect);
  70. }
  71. },
  72. onLoad() {
  73. },
  74. onReady() {
  75. this.calcStickyTop()
  76. }
  77. }
  78. </script>
  79. <style>
  80. .page {
  81. flex: 1;
  82. padding: 0 15px;
  83. background-color: #f5f5f5;
  84. }
  85. .content-item {
  86. padding: 15px;
  87. margin: 5px 0;
  88. background-color: #fff;
  89. border-radius: 5px;
  90. }
  91. .text {
  92. font-size: 14px;
  93. color: #666;
  94. line-height: 20px;
  95. }
  96. .search {
  97. background-color: #FFFFFF;
  98. border: 1px solid #fbdf0d;
  99. height: 35px;
  100. border-radius: 100px;
  101. margin: 0 12px;
  102. padding: 8px;
  103. flex-direction: row;
  104. align-items: center;
  105. justify-content: space-between;
  106. z-index: 100;
  107. }
  108. .search-tip-text {
  109. font-size: 12px;
  110. color: #666;
  111. }
  112. .search-btn {
  113. font-size: 12px;
  114. background-color: #ff6900;
  115. color: #FFF;
  116. padding: 5px 8px;
  117. border-radius: 100px;
  118. }
  119. </style>