large-header.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <template>
  2. <view :class="`large-header large-header-${mode}`" :style="{height: safeFullHeight}">
  3. <view class="fx-col justify-center" :style="{height: titleHeight+'px', ...titleStyle}">
  4. <mx-nav-bar :title="title" v-bind="navBinding"/>
  5. </view>
  6. <slot>
  7. <view class="fx-row justify-between px-40" :class="contentCustomClass">
  8. <view class="fx-col">
  9. <text class="text-3xl font-bold keep-all" :class="textColor">{{ subTitle }}</text>
  10. <text class="mt-10 text-sm keep-all" :class="textColor">{{ description }}</text>
  11. </view>
  12. <uv-image :src="bgIcon" width="auto" :height="bgIconHeight" mode="heightFix"/>
  13. </view>
  14. </slot>
  15. </view>
  16. </template>
  17. <script>
  18. export default {
  19. name: "large-header",
  20. props: {
  21. mode: {
  22. type: String,
  23. default: "dark",
  24. validator: (val) => ['dark', 'light'].includes(val)
  25. },
  26. title: {
  27. type: String,
  28. default: ""
  29. },
  30. bgIcon: {
  31. type: String,
  32. default: "/static/ie/entry/bg-large-header.png"
  33. },
  34. bgIconHeight: {
  35. // height fix mode make image display smooth.
  36. type: [String, Number],
  37. default: 130
  38. },
  39. titleStyle: {
  40. type: Object,
  41. default: () => ({})
  42. },
  43. subTitle: {
  44. type: String,
  45. default: ""
  46. },
  47. description: {
  48. type: String,
  49. default: ""
  50. },
  51. scrollTop: {
  52. type: Number,
  53. default: 0
  54. },
  55. navHeight: {
  56. type: Number,
  57. default: 44
  58. },
  59. titleHeight: {
  60. type: Number,
  61. default: 80
  62. },
  63. fullHeight: {
  64. type: [Number, String],
  65. default: 250
  66. },
  67. contentCustomClass: {
  68. type: String,
  69. default: 'items-center'
  70. }
  71. },
  72. computed: {
  73. safeFullHeight() {
  74. return isNaN(this.fullHeight) ? this.fullHeight : this.fullHeight + 'px'
  75. },
  76. space() {
  77. return (this.titleHeight - this.navHeight) / 2
  78. },
  79. darkMode() {
  80. return this.mode == "dark"
  81. },
  82. textColor() {
  83. return this.darkMode ? 'text-white' : 'text-primary'
  84. },
  85. navFixed() {
  86. return this.scrollTop > this.space
  87. },
  88. navOpacity() {
  89. if (!this.navFixed) return 0
  90. return Math.min(1, (this.scrollTop - this.space) / this.navHeight)
  91. },
  92. navBinding() {
  93. return {
  94. 'mode': this.mode,
  95. 'height': this.navHeight,
  96. 'fixed': this.navFixed,
  97. 'opacity': this.navOpacity,
  98. 'border': this.navOpacity == 1 && !this.darkMode,
  99. ...this.$attrs // other props consider as nav bindings.
  100. }
  101. }
  102. }
  103. }
  104. </script>
  105. <style scoped lang="scss">
  106. .large-header {
  107. overflow: hidden;
  108. &-dark {
  109. background: linear-gradient(to bottom, var(--primary-light-color), var(--primary-deep-color));
  110. }
  111. }
  112. </style>