index.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import { use } from '../utils';
  2. import Icon from '../icon';
  3. const [sfc, bem] = use('notice-bar');
  4. export default sfc({
  5. props: {
  6. text: String,
  7. mode: String,
  8. color: String,
  9. leftIcon: String,
  10. wrapable: Boolean,
  11. background: String,
  12. delay: {
  13. type: [String, Number],
  14. default: 1
  15. },
  16. scrollable: {
  17. type: Boolean,
  18. default: true
  19. },
  20. speed: {
  21. type: Number,
  22. default: 50
  23. }
  24. },
  25. data() {
  26. return {
  27. wrapWidth: 0,
  28. firstRound: true,
  29. duration: 0,
  30. offsetWidth: 0,
  31. showNoticeBar: true,
  32. animationClass: ''
  33. };
  34. },
  35. watch: {
  36. text: {
  37. handler() {
  38. this.$nextTick(() => {
  39. const { wrap, content } = this.$refs;
  40. if (!wrap || !content) {
  41. return;
  42. }
  43. const wrapWidth = wrap.getBoundingClientRect().width;
  44. const offsetWidth = content.getBoundingClientRect().width;
  45. if (this.scrollable && offsetWidth > wrapWidth) {
  46. this.wrapWidth = wrapWidth;
  47. this.offsetWidth = offsetWidth;
  48. this.duration = offsetWidth / this.speed;
  49. this.animationClass = bem('play');
  50. }
  51. });
  52. },
  53. immediate: true
  54. }
  55. },
  56. methods: {
  57. onClickIcon() {
  58. if (this.mode === 'closeable') {
  59. this.showNoticeBar = false;
  60. this.$emit('close');
  61. }
  62. },
  63. onAnimationEnd() {
  64. this.firstRound = false;
  65. this.$nextTick(() => {
  66. this.duration = (this.offsetWidth + this.wrapWidth) / this.speed;
  67. this.animationClass = bem('play--infinite');
  68. });
  69. }
  70. },
  71. render(h) {
  72. const { mode } = this;
  73. const iconName = mode === 'closeable' ? 'cross' : mode === 'link' ? 'arrow' : '';
  74. const barStyle = {
  75. color: this.color,
  76. background: this.background
  77. };
  78. const contentStyle = {
  79. paddingLeft: this.firstRound ? 0 : this.wrapWidth + 'px',
  80. animationDelay: (this.firstRound ? this.delay : 0) + 's',
  81. animationDuration: this.duration + 's'
  82. };
  83. return (
  84. <div
  85. vShow={this.showNoticeBar}
  86. class={bem({ withicon: mode, wrapable: this.wrapable })}
  87. style={barStyle}
  88. onClick={() => {
  89. this.$emit('click');
  90. }}
  91. >
  92. {this.leftIcon && (
  93. <Icon class={bem('left-icon')} name={this.leftIcon} />
  94. )}
  95. <div ref="wrap" class={bem('wrap')}>
  96. <div
  97. ref="content"
  98. class={[
  99. bem('content'),
  100. this.animationClass,
  101. { 'van-ellipsis': !this.scrollable && !this.wrapable }
  102. ]}
  103. style={contentStyle}
  104. onAnimationend={this.onAnimationEnd}
  105. onWebkitAnimationEnd={this.onAnimationEnd}
  106. >
  107. {this.slots() || this.text}
  108. </div>
  109. </div>
  110. {iconName && (
  111. <Icon
  112. class={bem('right-icon')}
  113. name={iconName}
  114. onClick={this.onClickIcon}
  115. />
  116. )}
  117. </div>
  118. );
  119. }
  120. });