index.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <view
  3. v-if="show"
  4. :class="'custom-class ' + utils.bem('notice-bar', { withicon: mode, wrapable })"
  5. :style="'color: ' + color + '; background-color: ' + backgroundColor + ';'"
  6. @tap="onClick"
  7. >
  8. <van-icon v-if="leftIcon" size="16px" :name="leftIcon" class="van-notice-bar__left-icon" />
  9. <slot v-else name="left-icon" />
  10. <view class="van-notice-bar__wrap">
  11. <view :class="'van-notice-bar__content ' + (!scrollable && !wrapable ? 'van-ellipsis' : '')" :animation="animationData">
  12. {{ text }}
  13. </view>
  14. </view>
  15. <van-icon v-if="mode === 'closeable'" class="van-notice-bar__right-icon" name="cross" @tap.native.stop.prevent="onClickIcon" />
  16. <navigator v-else-if="mode === 'link'" :url="url" :open-type="openType">
  17. <van-icon class="van-notice-bar__right-icon" name="arrow" />
  18. </navigator>
  19. <slot v-else name="right-icon" />
  20. </view>
  21. </template>
  22. <script module="utils" lang="wxs" src="@/node_modules/@vant/weapp/dist/wxs/utils.wxs"></script>
  23. <script>
  24. import { VantComponent } from '../common/component';
  25. const FONT_COLOR = '#ed6a0c';
  26. const BG_COLOR = '#fffbe8';
  27. export default {
  28. data() {
  29. return {
  30. show: true,
  31. animationData: ''
  32. };
  33. },
  34. props: {
  35. text: {
  36. type: String,
  37. default: ''
  38. },
  39. mode: {
  40. type: String,
  41. default: ''
  42. },
  43. url: {
  44. type: String,
  45. default: ''
  46. },
  47. openType: {
  48. type: String,
  49. default: 'navigate'
  50. },
  51. delay: {
  52. type: Number,
  53. default: 1
  54. },
  55. speed: {
  56. type: Number,
  57. default: 50
  58. },
  59. scrollable: {
  60. type: Boolean,
  61. default: true
  62. },
  63. leftIcon: {
  64. type: String,
  65. default: ''
  66. },
  67. color: {
  68. type: String,
  69. default: FONT_COLOR
  70. },
  71. backgroundColor: {
  72. type: String,
  73. default: BG_COLOR
  74. },
  75. wrapable: Boolean
  76. },
  77. created() {
  78. this.resetAnimation = uni.createAnimation({
  79. duration: 0,
  80. timingFunction: 'linear'
  81. });
  82. },
  83. destroyed() {
  84. if (this.timer) {
  85. clearTimeout(this.timer);
  86. }
  87. },
  88. methods: {
  89. init() {
  90. Promise.all([this.getRect('.van-notice-bar__content'), this.getRect('.van-notice-bar__wrap')]).then((rects) => {
  91. const [contentRect, wrapRect] = rects;
  92. if (contentRect == null || wrapRect == null || !contentRect.width || !wrapRect.width) {
  93. return;
  94. }
  95. const { speed, scrollable, delay } = this;
  96. if (scrollable && wrapRect.width < contentRect.width) {
  97. const duration = (contentRect.width / speed) * 1000;
  98. this.wrapWidth = wrapRect.width;
  99. this.contentWidth = contentRect.width;
  100. this.duration = duration;
  101. this.animation = uni.createAnimation({
  102. duration,
  103. timingFunction: 'linear',
  104. delay
  105. });
  106. this.scroll();
  107. }
  108. });
  109. },
  110. scroll() {
  111. if (this.timer) {
  112. clearTimeout(this.timer);
  113. }
  114. this.timer = null;
  115. this.setData({
  116. animationData: this.resetAnimation.translateX(this.wrapWidth).step().export()
  117. });
  118. setTimeout(() => {
  119. this.setData({
  120. animationData: this.animation.translateX(-this.contentWidth).step().export()
  121. });
  122. }, 20);
  123. this.timer = setTimeout(() => {
  124. this.scroll();
  125. }, this.duration);
  126. },
  127. onClickIcon() {
  128. if (this.timer) {
  129. clearTimeout(this.timer);
  130. }
  131. this.timer = null;
  132. this.setData({
  133. show: false
  134. });
  135. },
  136. onClick(event) {
  137. this.$emit('click', event);
  138. }
  139. },
  140. watch: {
  141. text: {
  142. handler: function () {
  143. this.$nextTick(() => {
  144. this.init();
  145. });
  146. },
  147. immediate: true
  148. },
  149. speed: {
  150. handler: function () {
  151. this.$nextTick(() => {
  152. this.init();
  153. });
  154. },
  155. immediate: true
  156. }
  157. }
  158. };
  159. </script>
  160. <style>
  161. @import './index.css';
  162. </style>