uni-notice-bar.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <template>
  2. <view v-if="show" class="uni-noticebar" :style="{ backgroundColor: backgroundColor }" @click="onClick">
  3. <!-- #ifdef MP-ALIPAY -->
  4. <view v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close uni-cursor-point"
  5. @click="close">
  6. <uni-icons type="closeempty" :color="color" size="12" />
  7. </view>
  8. <view v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon">
  9. <uni-icons type="sound" :color="color" size="14" />
  10. </view>
  11. <!-- #endif -->
  12. <!-- #ifndef MP-ALIPAY -->
  13. <uni-icons v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close uni-cursor-point"
  14. type="closeempty" :color="color" size="12" @click="close" />
  15. <uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound"
  16. :color="color" size="14" />
  17. <!-- #endif -->
  18. <view ref="textBox" class="uni-noticebar__content-wrapper"
  19. :class="{'uni-noticebar__content-wrapper--scrollable':scrollable, 'scrollStyle':portList.length!=0, 'uni-noticebar__content-wrapper--single':!scrollable && (single || moreText)}">
  20. <view :id="elIdBox" class="uni-noticebar__content"
  21. :class="{'uni-noticebar__content--scrollable':scrollable, 'scrollStyle1':portList.length!=0,'uni-noticebar__content--single':!scrollable && (single || moreText)}">
  22. <text v-if="portList.length==0" :id="elId" ref="animationEle" class="uni-noticebar__content-text"
  23. :class="{'uni-noticebar__content-text--scrollable':scrollable,'uni-noticebar__content-text--single':!scrollable && (single || moreText)}"
  24. :style="{color:color, width:wrapWidth+'px', 'animationDuration': animationDuration, '-webkit-animationDuration': animationDuration ,animationPlayState: webviewHide?'paused':animationPlayState,'-webkit-animationPlayState':webviewHide?'paused':animationPlayState, animationDelay: animationDelay, '-webkit-animationDelay':animationDelay}">{{text}}</text>
  25. <view v-if="portList.length!=0" :id="elId" ref="animationEle" class="uni-noticebar__content-text"
  26. :class="{'uni-noticebar__content-text--scrollable':scrollable,'scrollStyle2':portList.length!=0,'uni-noticebar__content-text--single':!scrollable && (single || moreText)}" :style="{color:color, width:wrapWidth+'px', 'animationDuration': animationDuration, '-webkit-animationDuration': animationDuration ,animationPlayState: webviewHide?'paused':animationPlayState,'-webkit-animationPlayState':webviewHide?'paused':animationPlayState, animationDelay: animationDelay, '-webkit-animationDelay':animationDelay}">
  27. <view class='guess-section-wrap-content port'>
  28. <view class='guess-section-wrap-item clearfix' v-for='item in portList'>
  29. <view class='factory'>{{item.port}}</view>
  30. <view class='wrap'>{{item.goodsName}}</view>
  31. <view class='price'>
  32. <text class='currectprice'>{{item.price}}</text>
  33. 较昨日
  34. <image v-if='item.comparePrice>0' style="width:7.5px;height:9px;"
  35. src='@/static/img/homepage/shangsheng.png'></image>
  36. <image v-if='item.comparePrice<0' style="width:7.5px;height:9px;"
  37. src='@/static/img/homepage/xiajiang.png'></image>
  38. <text v-if='item.comparePrice>0' class='yesterday up'>{{item.comparePrice}}</text>
  39. <text v-if='item.comparePrice<0' class='yesterday down'>{{-item.comparePrice}}</text>
  40. <text v-if='item.comparePrice==0' class='yesterday'>-</text>
  41. </view>
  42. <view style='color:#B2B3BB;' class='flex'>
  43. <view style='margin-right:10px;'>
  44. <image style='width:11px;height:11px;' src='@/static/img/homepage/water@3x.png'>
  45. </image>
  46. <={{item.waterContent}} </view>
  47. <view>
  48. <image style='width:11px;height:11px;'
  49. src='@/static/img/homepage/unitweight@3x.png'></image>
  50. >={{item.bulkDensity}}
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. </view>
  57. </view>
  58. <view v-if="showGetMore === true || showGetMore === 'true'" class="uni-noticebar__more uni-cursor-point"
  59. @click="clickMore">
  60. <text v-if="moreText" :style="{ color: moreColor }" class="uni-noticebar__more-text">{{ moreText }}</text>
  61. <uni-icons type="arrowright" :color="moreColor" size="14" />
  62. </view>
  63. </view>
  64. </template>
  65. <script>
  66. // #ifdef APP-NVUE
  67. const dom = weex.requireModule('dom');
  68. const animation = weex.requireModule('animation');
  69. // #endif
  70. /**
  71. * NoticeBar 自定义导航栏
  72. * @description 通告栏组件
  73. * @tutorial https://ext.dcloud.net.cn/plugin?id=30
  74. * @property {Number} speed 文字滚动的速度,默认100px/秒
  75. * @property {String} text 显示文字
  76. * @property {String} backgroundColor 背景颜色
  77. * @property {String} color 文字颜色
  78. * @property {String} moreColor 查看更多文字的颜色
  79. * @property {String} moreText 设置“查看更多”的文本
  80. * @property {Boolean} single = [true|false] 是否单行
  81. * @property {Boolean} scrollable = [true|false] 是否滚动,为true时,NoticeBar为单行
  82. * @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
  83. * @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
  84. * @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标,为true时,NoticeBar为单行
  85. * @event {Function} click 点击 NoticeBar 触发事件
  86. * @event {Function} close 关闭 NoticeBar 触发事件
  87. * @event {Function} getmore 点击”查看更多“时触发事件
  88. */
  89. export default {
  90. name: 'UniNoticeBar',
  91. emits: ['click', 'getmore', 'close'],
  92. props: {
  93. portList: {
  94. type: Array,
  95. default: ''
  96. },
  97. text: {
  98. type: String,
  99. default: ''
  100. },
  101. moreText: {
  102. type: String,
  103. default: ''
  104. },
  105. backgroundColor: {
  106. type: String,
  107. default: '#fffbe8'
  108. },
  109. speed: {
  110. // 默认1s滚动100px
  111. type: Number,
  112. default: 8
  113. },
  114. color: {
  115. type: String,
  116. default: '#de8c17'
  117. },
  118. moreColor: {
  119. type: String,
  120. default: '#999999'
  121. },
  122. single: {
  123. // 是否单行
  124. type: [Boolean, String],
  125. default: false
  126. },
  127. scrollable: {
  128. // 是否滚动,添加后控制单行效果取消
  129. type: [Boolean, String],
  130. default: false
  131. },
  132. showIcon: {
  133. // 是否显示左侧icon
  134. type: [Boolean, String],
  135. default: false
  136. },
  137. showGetMore: {
  138. // 是否显示右侧查看更多
  139. type: [Boolean, String],
  140. default: false
  141. },
  142. showClose: {
  143. // 是否显示左侧关闭按钮
  144. type: [Boolean, String],
  145. default: false
  146. }
  147. },
  148. data() {
  149. const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
  150. const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
  151. return {
  152. textWidth: 0,
  153. boxWidth: 0,
  154. wrapWidth: '',
  155. webviewHide: false,
  156. // #ifdef APP-NVUE
  157. stopAnimation: false,
  158. // #endif
  159. elId: elId,
  160. elIdBox: elIdBox,
  161. show: true,
  162. animationDuration: 'none',
  163. animationPlayState: 'paused',
  164. animationDelay: '0s'
  165. }
  166. },
  167. mounted() {
  168. // #ifdef APP-PLUS
  169. var pages = getCurrentPages();
  170. var page = pages[pages.length - 1];
  171. var currentWebview = page.$getAppWebview();
  172. currentWebview.addEventListener('hide', () => {
  173. this.webviewHide = true
  174. })
  175. currentWebview.addEventListener('show', () => {
  176. this.webviewHide = false
  177. })
  178. // #endif
  179. this.$nextTick(() => {
  180. this.initSize()
  181. })
  182. },
  183. // #ifdef APP-NVUE
  184. beforeDestroy() {
  185. this.stopAnimation = true
  186. },
  187. // #endif
  188. methods: {
  189. initSize() {
  190. if (this.scrollable) {
  191. // #ifndef APP-NVUE
  192. let query = [],
  193. boxWidth = 0,
  194. textWidth = 0;
  195. let textQuery = new Promise((resolve, reject) => {
  196. uni.createSelectorQuery()
  197. // #ifndef MP-ALIPAY
  198. .in(this)
  199. // #endif
  200. .select(`#${this.elId}`)
  201. .boundingClientRect()
  202. .exec(ret => {
  203. this.textWidth = ret[0].width
  204. resolve()
  205. })
  206. })
  207. let boxQuery = new Promise((resolve, reject) => {
  208. uni.createSelectorQuery()
  209. // #ifndef MP-ALIPAY
  210. .in(this)
  211. // #endif
  212. .select(`#${this.elIdBox}`)
  213. .boundingClientRect()
  214. .exec(ret => {
  215. this.boxWidth = ret[0].width
  216. resolve()
  217. })
  218. })
  219. query.push(textQuery)
  220. query.push(boxQuery)
  221. Promise.all(query).then(() => {
  222. this.animationDuration = `${this.textWidth / this.speed}s`
  223. this.animationDelay = `-${this.boxWidth / this.speed}s`
  224. setTimeout(() => {
  225. this.animationPlayState = 'running'
  226. }, 1000)
  227. })
  228. // #endif
  229. // #ifdef APP-NVUE
  230. dom.getComponentRect(this.$refs['animationEle'], (res) => {
  231. let winWidth = uni.getSystemInfoSync().windowWidth
  232. this.textWidth = res.size.width
  233. animation.transition(this.$refs['animationEle'], {
  234. styles: {
  235. transform: `translateX(-${winWidth}px)`
  236. },
  237. duration: 0,
  238. timingFunction: 'linear',
  239. delay: 0
  240. }, () => {
  241. if (!this.stopAnimation) {
  242. animation.transition(this.$refs['animationEle'], {
  243. styles: {
  244. transform: `translateX(-${this.textWidth}px)`
  245. },
  246. timingFunction: 'linear',
  247. duration: (this.textWidth - winWidth) / this.speed * 1000,
  248. delay: 1000
  249. }, () => {
  250. if (!this.stopAnimation) {
  251. this.loopAnimation()
  252. }
  253. });
  254. }
  255. });
  256. })
  257. // #endif
  258. }
  259. // #ifdef APP-NVUE
  260. if (!this.scrollable && (this.single || this.moreText)) {
  261. dom.getComponentRect(this.$refs['textBox'], (res) => {
  262. this.wrapWidth = res.size.width
  263. })
  264. }
  265. // #endif
  266. },
  267. loopAnimation() {
  268. // #ifdef APP-NVUE
  269. animation.transition(this.$refs['animationEle'], {
  270. styles: {
  271. transform: `translateX(0px)`
  272. },
  273. duration: 0
  274. }, () => {
  275. if (!this.stopAnimation) {
  276. animation.transition(this.$refs['animationEle'], {
  277. styles: {
  278. transform: `translateX(-${this.textWidth}px)`
  279. },
  280. duration: this.textWidth / this.speed * 1000,
  281. timingFunction: 'linear',
  282. delay: 0
  283. }, () => {
  284. if (!this.stopAnimation) {
  285. this.loopAnimation()
  286. }
  287. });
  288. }
  289. });
  290. // #endif
  291. },
  292. clickMore() {
  293. this.$emit('getmore')
  294. },
  295. close() {
  296. this.show = false;
  297. this.$emit('close')
  298. },
  299. onClick() {
  300. this.$emit('click')
  301. }
  302. }
  303. }
  304. </script>
  305. <style lang="scss" scoped>
  306. .uni-noticebar {
  307. /* #ifndef APP-NVUE */
  308. display: flex;
  309. width: 100%;
  310. box-sizing: border-box;
  311. /* #endif */
  312. flex-direction: row;
  313. align-items: center;
  314. padding: 6px 12px;
  315. margin-bottom: 10px;
  316. }
  317. .uni-cursor-point {
  318. /* #ifdef H5 */
  319. cursor: pointer;
  320. /* #endif */
  321. }
  322. .uni-noticebar-close {
  323. margin-right: 5px;
  324. }
  325. .uni-noticebar-icon {
  326. margin-right: 5px;
  327. }
  328. .uni-noticebar__content-wrapper {
  329. flex: 1;
  330. flex-direction: column;
  331. overflow: hidden;
  332. }
  333. .uni-noticebar__content-wrapper--single {
  334. /* #ifndef APP-NVUE */
  335. line-height: 18px;
  336. /* #endif */
  337. }
  338. .uni-noticebar__content-wrapper--single,
  339. .uni-noticebar__content-wrapper--scrollable {
  340. flex-direction: row;
  341. }
  342. /* #ifndef APP-NVUE */
  343. .uni-noticebar__content-wrapper--scrollable {
  344. position: relative;
  345. height: 18px;
  346. }
  347. /* #endif */
  348. .uni-noticebar__content--scrollable {
  349. /* #ifdef APP-NVUE */
  350. flex: 0;
  351. /* #endif */
  352. /* #ifndef APP-NVUE */
  353. flex: 1;
  354. display: block;
  355. overflow: hidden;
  356. /* #endif */
  357. }
  358. .uni-noticebar__content--single {
  359. /* #ifndef APP-NVUE */
  360. display: flex;
  361. flex: none;
  362. width: 100%;
  363. justify-content: center;
  364. /* #endif */
  365. }
  366. .uni-noticebar__content-text {
  367. font-size: 14px;
  368. line-height: 18px;
  369. /* #ifndef APP-NVUE */
  370. word-break: break-all;
  371. /* #endif */
  372. }
  373. .uni-noticebar__content-text--single {
  374. /* #ifdef APP-NVUE */
  375. lines: 1;
  376. /* #endif */
  377. /* #ifndef APP-NVUE */
  378. display: block;
  379. width: 100%;
  380. white-space: nowrap;
  381. /* #endif */
  382. overflow: hidden;
  383. text-overflow: ellipsis;
  384. }
  385. .uni-noticebar__content-text--scrollable {
  386. /* #ifdef APP-NVUE */
  387. lines: 1;
  388. padding-left: 750rpx;
  389. /* #endif */
  390. /* #ifndef APP-NVUE */
  391. position: absolute;
  392. display: block;
  393. height: 18px;
  394. line-height: 18px;
  395. white-space: nowrap;
  396. padding-left: 100%;
  397. animation: notice 10s 0s linear infinite both;
  398. animation-play-state: paused;
  399. /* #endif */
  400. }
  401. .uni-noticebar__more {
  402. /* #ifndef APP-NVUE */
  403. display: inline-flex;
  404. /* #endif */
  405. flex-direction: row;
  406. flex-wrap: nowrap;
  407. align-items: center;
  408. padding-left: 5px;
  409. }
  410. .uni-noticebar__more-text {
  411. font-size: 14px;
  412. }
  413. @keyframes notice {
  414. 100% {
  415. transform: translate3d(-100%, 0, 0);
  416. }
  417. }
  418. .guess-section-wrap-content{
  419. display: flex;
  420. }
  421. .scrollStyle{
  422. height: 100px;
  423. display: flex;
  424. justify-content: center;
  425. // align-items: center;
  426. }
  427. .scrollStyle1{
  428. // background: red;
  429. display: felx;
  430. align-items: center;
  431. }
  432. .scrollStyle2{
  433. // background: yellow;
  434. display: felx;
  435. align-items: center;
  436. height: 100%;
  437. }
  438. .guess-section-wrap-content{
  439. height: 100%;
  440. display: flex;
  441. align-items: center;
  442. }
  443. .guess-section-wrap-item {
  444. float: left;
  445. width: 38vw;
  446. background: #F9F9FA;
  447. padding: 10px;
  448. margin: 10px;
  449. border-radius: 3px;
  450. color: black;
  451. // width:50%;
  452. }
  453. .factory{
  454. font-size: 13px;
  455. font-weight: 900;
  456. }
  457. .wrap{
  458. font-size: 10px;
  459. color: rgba(0, 0, 0, 0.5);
  460. }
  461. .price{
  462. color: #B2B3BB;
  463. }
  464. .currectprice{
  465. color: #fd714f;
  466. font-size: 18px;
  467. font-weight: 600;
  468. vertical-align: middle;
  469. margin-right: 10px;
  470. }
  471. </style>