index.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. const VALID_MODE = ['closeable', 'link'];
  2. const FONT_COLOR = '#f60';
  3. const BG_COLOR = '#fff7cc';
  4. Component({
  5. externalClasses: ['custom-class'],
  6. properties: {
  7. text: {
  8. type: String,
  9. value: '',
  10. observer() {
  11. this.setData({}, this._init);
  12. }
  13. },
  14. mode: {
  15. type: String,
  16. value: ''
  17. },
  18. url: {
  19. type: String,
  20. value: ''
  21. },
  22. openType: {
  23. type: String,
  24. value: 'navigate'
  25. },
  26. delay: {
  27. type: Number,
  28. value: 0
  29. },
  30. speed: {
  31. type: Number,
  32. value: 50
  33. },
  34. scrollable: {
  35. type: Boolean,
  36. value: true
  37. },
  38. leftIcon: {
  39. type: String,
  40. value: ''
  41. },
  42. color: {
  43. type: String,
  44. value: FONT_COLOR
  45. },
  46. backgroundColor: {
  47. type: String,
  48. value: BG_COLOR
  49. }
  50. },
  51. data: {
  52. show: true,
  53. hasRightIcon: false,
  54. width: undefined,
  55. wrapWidth: undefined,
  56. elapse: undefined,
  57. animation: null,
  58. resetAnimation: null,
  59. timer: null
  60. },
  61. attached() {
  62. const { mode } = this.data;
  63. if (mode && this._checkMode(mode)) {
  64. this.setData({
  65. hasRightIcon: true
  66. });
  67. }
  68. },
  69. detached() {
  70. const { timer } = this.data;
  71. timer && clearTimeout(timer);
  72. },
  73. methods: {
  74. _checkMode(val) {
  75. const isValidMode = ~VALID_MODE.indexOf(val);
  76. if (!isValidMode) {
  77. console.warn(`mode only accept value of ${VALID_MODE}, now get ${val}.`);
  78. }
  79. return isValidMode;
  80. },
  81. _init() {
  82. wx.createSelectorQuery()
  83. .in(this)
  84. .select('.van-notice-bar__content')
  85. .boundingClientRect((rect) => {
  86. if (!rect || !rect.width) {
  87. return;
  88. }
  89. this.setData({
  90. width: rect.width
  91. });
  92. wx.createSelectorQuery()
  93. .in(this)
  94. .select('.van-notice-bar__content-wrap')
  95. .boundingClientRect((rect) => {
  96. if (!rect || !rect.width) {
  97. return;
  98. }
  99. const wrapWidth = rect.width;
  100. const {
  101. width, speed, scrollable, delay
  102. } = this.data;
  103. if (scrollable && wrapWidth < width) {
  104. const elapse = width / speed * 1000;
  105. const animation = wx.createAnimation({
  106. duration: elapse,
  107. timeingFunction: 'linear',
  108. delay
  109. });
  110. const resetAnimation = wx.createAnimation({
  111. duration: 0,
  112. timeingFunction: 'linear'
  113. });
  114. this.setData({
  115. elapse,
  116. wrapWidth,
  117. animation,
  118. resetAnimation
  119. }, () => {
  120. this._scroll();
  121. });
  122. }
  123. })
  124. .exec();
  125. })
  126. .exec();
  127. },
  128. _scroll() {
  129. const {
  130. animation, resetAnimation, wrapWidth, elapse, speed
  131. } = this.data;
  132. resetAnimation.translateX(wrapWidth).step();
  133. const animationData = animation.translateX(-(elapse * speed) / 1000).step();
  134. this.setData({
  135. animationData: resetAnimation.export()
  136. });
  137. setTimeout(() => {
  138. this.setData({
  139. animationData: animationData.export()
  140. });
  141. }, 100);
  142. const timer = setTimeout(() => {
  143. this._scroll();
  144. }, elapse);
  145. this.setData({
  146. timer
  147. });
  148. },
  149. _handleButtonClick() {
  150. const { timer } = this.data;
  151. timer && clearTimeout(timer);
  152. this.setData({
  153. show: false,
  154. timer: null
  155. });
  156. },
  157. onClick(event) {
  158. this.triggerEvent('click', event);
  159. }
  160. }
  161. });