uni-notice-bar.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <template>
  2. <view v-if="show" :style="{backgroundColor:backgroundColor,color:color}" class="uni-noticebar" @click="onClick">
  3. <view v-if="showClose" class="uni-noticebar__close">
  4. <uni-icon type="closefill" size="12" />
  5. </view>
  6. <view :class="{'uni-noticebar--flex': scrollable || single || moreText}" class="uni-noticebar__content">
  7. <view v-if="showIcon" :style="{backgroundColor:backgroundColor,color:color}" class="uni-noticebar__content-icon">
  8. <uni-icon :color="color" type="sound" size="14" />
  9. </view>
  10. <view :class="{'uni-noticebar--scrollable':scrollable,'uni-noticebar--single':!scrollable && (single || moreText)}" class="uni-noticebar__content-text">
  11. <view :id="elId" :style="{'animation': animation,'-webkit-animation': animation}" class="uni-noticebar__content-inner">{{ text }}</view>
  12. </view>
  13. <view v-if="showGetMore" :style="{width:moreText ? '180upx' : '20px'}" class="uni-noticebar__content-more" @click="clickMore">
  14. <view v-if="moreText" class="uni-noticebar__content-more-text">{{ moreText }}</view>
  15. <uni-icon type="arrowright" size="14" />
  16. </view>
  17. </view>
  18. </view>
  19. </template>
  20. <script>
  21. import uniIcon from '../uni-icon/uni-icon.vue'
  22. export default {
  23. name: 'UniNoticeBar',
  24. components: {
  25. uniIcon
  26. },
  27. props: {
  28. text: {
  29. type: String,
  30. default: ''
  31. },
  32. moreText: {
  33. type: String,
  34. default: ''
  35. },
  36. backgroundColor: {
  37. type: String,
  38. default: '#fffbe8'
  39. },
  40. speed: { // 默认1s滚动100px
  41. type: [String, Number],
  42. default: 100
  43. },
  44. color: {
  45. type: String,
  46. default: '#de8c17'
  47. },
  48. single: { // 是否单行
  49. type: Boolean,
  50. default: false
  51. },
  52. scrollable: { // 是否滚动,添加后控制单行效果取消
  53. type: Boolean,
  54. default: false
  55. },
  56. showIcon: { // 是否显示左侧icon
  57. type: Boolean,
  58. default: false
  59. },
  60. showGetMore: { // 是否显示右侧查看更多
  61. type: Boolean,
  62. default: false
  63. },
  64. showClose: { // 是否显示左侧关闭按钮
  65. type: Boolean,
  66. default: false
  67. }
  68. },
  69. data() {
  70. /**
  71. * TODO 兼容新旧编译器
  72. * 新编译器(自定义组件模式)下必须使用固定数值,否则部分平台下会获取不到节点。
  73. * 随机数值是在旧编译器下使用的,旧编译器模式已经不推荐使用,后续直接废掉随机数值的写法。
  74. */
  75. const elId = this.__call_hook ? 'uni_notice_bar' : `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
  76. return {
  77. elId: elId,
  78. show: true,
  79. animation: ''
  80. }
  81. },
  82. watch: {
  83. text(newValue, oldValue) {
  84. this.$nextTick(() => {
  85. setTimeout(this.setAnimation, 200)
  86. })
  87. }
  88. },
  89. // #ifdef H5
  90. mounted() {
  91. this.setAnimation()
  92. },
  93. // #endif
  94. // #ifndef H5
  95. onReady() {
  96. this.setAnimation()
  97. },
  98. // #endif
  99. methods: {
  100. clickMore() {
  101. this.$emit('getmore')
  102. },
  103. onClick(e) {
  104. let clientX = e.touches ? (e.touches[0] ? e.touches[0].clientX : e.changedTouches[0].clientX) : e.detail.clientX
  105. if (uni.upx2px(48) + 12 > clientX && this.showClose) {
  106. this.show = false
  107. this.$emit('close')
  108. }
  109. this.$emit('click')
  110. },
  111. setAnimation() {
  112. if (!this.scrollable) {
  113. return
  114. }
  115. // #ifdef MP-TOUTIAO
  116. setTimeout(() => {
  117. uni.createSelectorQuery().in(this).select(`#${this.elId}`).boundingClientRect().exec((ret) => {
  118. this.animation = `notice ${ret[0].width / this.speed}s linear infinite both`
  119. })
  120. }, 200)
  121. // #endif
  122. // #ifndef MP-TOUTIAO
  123. uni.createSelectorQuery().in(this).select(`#${this.elId}`).boundingClientRect().exec((ret) => {
  124. this.animation = `notice ${ret[0].width / this.speed}s linear infinite both`
  125. })
  126. // #endif
  127. }
  128. }
  129. }
  130. </script>
  131. <style>
  132. @charset "UTF-8";
  133. .uni-noticebar {
  134. padding: 12upx 24upx;
  135. font-size: 24upx;
  136. line-height: 1.5;
  137. margin-bottom: 20upx;
  138. display: flex;
  139. flex-direction: row;
  140. justify-content: center;
  141. align-items: center;
  142. justify-content: left
  143. }
  144. .uni-noticebar__close {
  145. color: #999;
  146. margin-right: 24upx;
  147. display: flex;
  148. flex-direction: row;
  149. justify-content: center;
  150. align-items: center
  151. }
  152. .uni-noticebar__content {
  153. flex: 1;
  154. overflow: hidden
  155. }
  156. .uni-noticebar__content.uni-noticebar--flex {
  157. flex: 1;
  158. display: flex;
  159. flex-direction: row
  160. }
  161. .uni-noticebar__content-icon {
  162. display: inline-block;
  163. z-index: 1;
  164. padding-right: 12upx
  165. }
  166. .uni-noticebar__content-more {
  167. width: 180upx;
  168. display: flex;
  169. flex-direction: row;
  170. justify-content: center;
  171. align-items: center;
  172. justify-content: flex-end;
  173. word-break: keep-all;
  174. margin-left: 10upx;
  175. color: #999
  176. }
  177. .uni-noticebar__content-more-text {
  178. font-size: 24upx;
  179. white-space: nowrap
  180. }
  181. .uni-noticebar__content-text {
  182. word-break: break-all;
  183. line-height: 1.5;
  184. display: inline
  185. }
  186. .uni-noticebar__content-text.uni-noticebar--single {
  187. text-overflow: ellipsis;
  188. white-space: nowrap;
  189. overflow: hidden
  190. }
  191. .uni-noticebar__content-text.uni-noticebar--scrollable {
  192. flex: 1;
  193. display: block;
  194. overflow: hidden
  195. }
  196. .uni-noticebar__content-text.uni-noticebar--scrollable .uni-noticebar__content-inner {
  197. padding-left: 100%;
  198. white-space: nowrap;
  199. display: inline-block;
  200. transform: translateZ(0)
  201. }
  202. .uni-noticebar__content-inner {
  203. font-size: 24upx;
  204. display: inline
  205. }
  206. @keyframes notice {
  207. 100% {
  208. transform: translate3d(-100%, 0, 0)
  209. }
  210. }
  211. </style>