marquee.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. <template>
  2. <view class="marquee_box" @touchstart='touchstartFn' @touchend='touchendFn'>
  3. <view class="" v-if="direction=='right'||direction=='left'">
  4. <view v-if="broadcastType=='text'" class="marquee_container" :style="'background:'+broadcastStylees.back_color+';'">
  5. <view v-if="broadcastIconIsDisplay" class="broadIcon" :style="'background:'+broadcastStylees.back_color+';font-size:28rpx;'">
  6. <text class="iconfont icon-guangbozheng-"></text>
  7. <text style="margin-left:12rpx;">{{broadcast_tit}}:</text>
  8. </view>
  9. <view class="boradcast_text_left_rig" :class='[direction=="left"?"marquee_text_left":direction=="right"?"marquee_text_right":"",animation_paused?"animation_pausedcss":""]'
  10. :style="'--marqueeWidth--:'+(-broadcastStylees.width_mal)+'px;--speed--:'+broadcastStylees.time+'s;width:'+broadcastStylees.width_mal+'px;'">
  11. <view v-for="(item,index) in broadcastDataes" @click.stop="click_event(index)" :key="index" :style="'color:'+broadcastStylees.text_color+';margin-left:'+(index!=0?item.starspos:0)+'px;font-size:'+broadcastStylees.font_size+'rpx;'">
  12. {{item.text}}
  13. </view>
  14. </view>
  15. </view>
  16. <view v-if="broadcastType=='mould'" class="mould">
  17. <view class="" style="width: 100%;position: relative;overflow: hidden;" :style="'height:'+viewHeight+'rpx;'">
  18. <view id="widthBox" class="broadcastTopBtm dsf" :class="[direction=='left'?'broadcastDataTopBtmDatacss_let':direction=='right'?'broadcastDataTopBtmDatacss_rig':'',animation_paused?'animation_pausedcss':'']"
  19. :style="styleWidth">
  20. <view class="bml01" style="display: flex;justify-content: space-between;">
  21. <view v-for="(item, index) in groupBookingList" :key="index" class="floor-item">
  22. <image class="list-image" :src="item.image"></image>
  23. <view class="tpl-box">
  24. <image mode="scaleToFill" src="https://shicai.liuniu946.com/img/img063.png"></image>
  25. <view class="price-list flex">
  26. <view class="out-price">¥{{ item.ot_price }}</view>
  27. <view class="xianprice">
  28. <text>¥{{ item.price }}</text>
  29. </view>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. <view class="bml02" style="display: flex;justify-content: space-between;">
  35. <view v-for="(item, index) in groupBookingList" :key="index" class="floor-item">
  36. <image class="list-image" :src="item.image"></image>
  37. <view class="tpl-box">
  38. <image mode="scaleToFill" src="https://shicai.liuniu946.com/img/img063.png"></image>
  39. <view class="price-list flex">
  40. <view class="out-price">¥{{ item.ot_price }}</view>
  41. <view class="xianprice">
  42. <text>¥{{ item.price }}</text>
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. </view>
  51. </view>
  52. <view v-if="direction=='top'||direction=='bottom'" class="broadcastTopBtm" :style="'font-size:'+broadcastStyle.font_size+'rpx;color:'+broadcastStyle.text_color+';background:'+broadcastStyle.back_color+';height:'+viewHeight+'rpx;--scrollHeight--:'+(-broadcastTopBtmHeight/2)+'px;--scrollSpeed--:'+(broadcastTopBtmHeight/2)/broadcastStyle.speed+'s;'">
  53. <view v-if="broadcastType=='text'" :class="[direction=='top'?'broadcastDataTopBtmDatacss_top':direction=='bottom'?'broadcastDataTopBtmDatacss_bottom':'',animation_paused?'animation_pausedcss':'']">
  54. <view v-for="(item,index) in broadcastDataTopBtmDataes"
  55. :key="index"
  56. @click.stop="click_event(index)"
  57. class="bdbd_item">
  58. <!-- {{item}} -->
  59. </view>
  60. </view>
  61. <view v-if="broadcastType=='mould'" :class="[direction=='top'?'broadcastDataTopBtmDatacss_top':direction=='bottom'?'broadcastDataTopBtmDatacss_bottom':'',animation_paused?'animation_pausedcss':'']">
  62. <view class="">
  63. <slot />
  64. </view>
  65. <view class="">
  66. <slot />
  67. </view>
  68. </view>
  69. </view>
  70. </view>
  71. </template>
  72. <script>
  73. /**
  74. * author:G.bro
  75. * date:20200513
  76. * * **/
  77. export default {
  78. data() {
  79. return {
  80. broadcastDataes: [],
  81. broadcastDataTopBtmDataes: [],
  82. broadcastStylees: {},
  83. broadcastTopBtmHeight: 0,
  84. scrlloWidth: 0,
  85. animation_paused: false,
  86. qualifications:true,
  87. styleWidth:''
  88. }
  89. },
  90. props: {
  91. groupBookingList:{
  92. default:function () {
  93. return []
  94. }
  95. },
  96. broadcastType: {
  97. type: String,
  98. default: 'text' //mould
  99. },
  100. // broadcastDataTopBtmData: {
  101. // type: Array
  102. // },
  103. broadcastData: {
  104. type: Array
  105. },
  106. broadcastStyle: {
  107. type: Object,
  108. default () {
  109. return {
  110. speed: 90, //滚动速度,每秒3个字
  111. font_size: "28", //字体大小(rpx)
  112. text_color: "#fff", //字体颜色
  113. back_color: "#815CD4", //背景色
  114. }
  115. }
  116. },
  117. broadcastIconIsDisplay: { //图标是否显示
  118. type: Boolean,
  119. default: false
  120. },
  121. // broadcast_icon: {
  122. // type: String,
  123. // default: ''
  124. // },
  125. broadcast_tit: {
  126. type: String,
  127. default: '今日热点'
  128. },
  129. direction: {
  130. type: String,
  131. default: 'left'
  132. },
  133. viewHeight: {
  134. type: Number,
  135. default: 200
  136. },
  137. touchEvent: {
  138. type: true,
  139. default: false
  140. }
  141. },
  142. comments: {
  143. },
  144. created() {
  145. if (this.broadcastType == "text") {
  146. if (this.direction == "right" || this.direction == "left") {
  147. this.initial_let_rig();
  148. } else {
  149. let arr = [...this.broadcastData];
  150. arr = arr.concat(arr);
  151. this.broadcastDataTopBtmDataes = arr;
  152. }
  153. }
  154. },
  155. mounted() {},
  156. methods: {
  157. getBoxWidth(){
  158. let that = this;
  159. if (this.direction == "top" || this.direction == "bottom") {
  160. const query2 = uni.createSelectorQuery().in(this)
  161. query2.select('.broadcastDataTopBtmDatacss_' + this.direction).boundingClientRect(rect => {
  162. that.broadcastTopBtmHeight = rect.height;
  163. if(that.viewHeight-rect.height>10){
  164. that.qualifications=false;
  165. that.animation_paused = true;
  166. that.broadcastDataTopBtmDataes.splice(that.broadcastDataTopBtmDataes.length/2,that.broadcastDataTopBtmDataes.length-1);
  167. }
  168. console.log(that.broadcastDataTopBtmDataes.length/2, 'that.surplusHeight')
  169. }).exec()
  170. }
  171. if (this.direction == "left" || this.direction == "right") {
  172. if (this.broadcastType == 'mould') {
  173. const query = uni.createSelectorQuery().in(this)
  174. query.select('.bml01').boundingClientRect(rect => {
  175. console.log(rect);
  176. that.scrlloWidth = +rect.width;
  177. let styleWidth='--scrollWidth--:-'+that.scrlloWidth+'px;--scrollSpeed2--:'+that.scrlloWidth/that.broadcastStyle.speed+'s;width:'+that.scrlloWidth*2+'px;'
  178. that.$set(that,'styleWidth',styleWidth);
  179. }).exec()
  180. query.select('.bml01').boundingClientRect(rect => {
  181. console.log(rect);
  182. that.scrlloWidth = +rect.width;
  183. let styleWidth='--scrollWidth--:-'+that.scrlloWidth+'px;--scrollSpeed2--:'+that.scrlloWidth/that.broadcastStyle.speed+'s;width:'+that.scrlloWidth*2+'px;'
  184. that.$set(that,'styleWidth',styleWidth);
  185. }).exec()
  186. }
  187. // if(this.broadcastType=='text'){有偏差
  188. // let assist = { ...this.broadcastStyle};
  189. // const querys = uni.createSelectorQuery().in(this)
  190. // querys.select('.boradcast_text_left_rig').boundingClientRect(rect => {
  191. // assist.width_mal = rect.width;
  192. // assist.time = rect.width/assist.speed;
  193. // that.broadcastStylees=assist;
  194. // }).exec()
  195. // }
  196. }
  197. },
  198. touchendFn(e) {
  199. if (this.touchEvent&&this.qualifications) {
  200. this.animation_paused = false;
  201. }
  202. },
  203. touchstartFn(e) {
  204. if (this.touchEvent&&this.qualifications) {
  205. this.animation_paused = true;
  206. }
  207. },
  208. initial_let_rig() {
  209. let broadcastData = [...this.broadcastData];
  210. console.log(this.direction, 'this.direction')
  211. if (this.direction == "right") {
  212. broadcastData.reverse();
  213. }
  214. let ititdata = broadcastData.map((item) => {
  215. return {
  216. "text": item,
  217. "starspos": uni.getSystemInfoSync().windowWidth - 103
  218. }
  219. }),
  220. assist = { ...this.broadcastStyle
  221. },
  222. this_width = 0,
  223. spacing = 0,
  224. speed = (assist.speed * assist.font_size); //m每秒行走的距离
  225. for (let i in ititdata) {
  226. this_width += ititdata[i].text.length * assist.font_size;
  227. if (i != ititdata.length - 1) {
  228. spacing += ititdata[i].starspos
  229. }
  230. }
  231. let total_length = (this_width / 2) + spacing; //总长
  232. assist.time = total_length / speed; /**滚动时间*/
  233. assist.width_mal = total_length;
  234. this.broadcastDataes = ititdata;
  235. this.broadcastStylees = assist;
  236. },
  237. click_event(index){
  238. let nub = this.broadcastDataTopBtmDataes.length/2;
  239. let dataNub=0;
  240. if(index>nub-1){
  241. dataNub = index -nub
  242. }else{
  243. dataNub = index;
  244. }
  245. this.$emit("changeEvent",{dataNub,msg:`你点击了${index+1}条`});
  246. }
  247. }
  248. }
  249. </script>
  250. <style lang="scss">
  251. .tpl-box {
  252. position: relative;
  253. image {
  254. width: 149rpx;
  255. height: 33rpx;
  256. }
  257. }
  258. .floor-item {
  259. margin: 0rpx 25rpx;
  260. .list-image {
  261. width: 140rpx;
  262. height: 140rpx;
  263. border-radius: 15rpx;
  264. }
  265. .price-list {
  266. font-size: 20rpx;
  267. position: absolute;
  268. top: 0;
  269. left: 0;
  270. width: 100%;
  271. padding: 5rpx 10rpx;
  272. line-height: 1;
  273. height: 33rpx;
  274. align-items: flex-end;
  275. .out-price {
  276. color: #b25e15;
  277. text-decoration: line-through;
  278. font-size: 17rpx;
  279. }
  280. .xianprice {
  281. color: #ffffff;
  282. font-size: 24rpx !important;
  283. // padding-bottom: 5rpx;
  284. }
  285. .moneyIcon {
  286. font-size: 17rpx;
  287. }
  288. }
  289. }
  290. /* page {
  291. overflow: hidden;
  292. width: 100%;
  293. } */
  294. .marquee_box {
  295. width: 100%;
  296. overflow: hidden;
  297. position: inherit;
  298. height: auto;
  299. }
  300. .mould {
  301. width: 750rpx;
  302. overflow: hidden;
  303. position: inherit;
  304. }
  305. .dsf {
  306. display: flex;
  307. justify-content: space-between;
  308. }
  309. .broadIcon {
  310. /* width: 60rpx; */
  311. padding: 0 22rpx;
  312. height: 60rpx;
  313. display: flex;
  314. justify-content: center;
  315. align-items: center;
  316. position: absolute;
  317. left: 0;
  318. top: 0;
  319. color: #fff;
  320. z-index: 999;
  321. line-height: 60rpx;
  322. }
  323. .marquee_container {
  324. position: relative;
  325. width: 100%;
  326. height: 60rpx;
  327. }
  328. .marquee_text_left {
  329. display: flex;
  330. white-space: nowrap;
  331. animation-name: around_left;
  332. animation-duration: var(--speed--);
  333. animation-iteration-count: infinite;
  334. animation-timing-function: linear;
  335. line-height: 60rpx;
  336. position: absolute;
  337. }
  338. @keyframes around_left {
  339. from {
  340. left: 100%;
  341. }
  342. to {
  343. left: var(--marqueeWidth--);
  344. }
  345. }
  346. .marquee_text_right {
  347. display: flex;
  348. white-space: nowrap;
  349. animation-name: around_right;
  350. animation-duration: var(--speed--);
  351. animation-iteration-count: infinite;
  352. animation-timing-function: linear;
  353. line-height: 60rpx;
  354. position: absolute;
  355. }
  356. @keyframes around_right {
  357. from {
  358. right: 100%;
  359. }
  360. to {
  361. right: var(--marqueeWidth--);
  362. }
  363. }
  364. .marquee_tit {
  365. height: 60rpx;
  366. line-height: 60rpx;
  367. }
  368. .broadcastTopBtm {
  369. padding: 12rx;
  370. overflow: hidden;
  371. position: relative;
  372. }
  373. .broadcastDataTopBtmDatacss_top {
  374. width: 100%;
  375. animation-name: around_top;
  376. animation-duration: var(--scrollSpeed--);
  377. animation-iteration-count: infinite;
  378. animation-timing-function: linear;
  379. position: absolute;
  380. left: 0;
  381. }
  382. @keyframes around_top {
  383. from {
  384. top: 0%;
  385. }
  386. to {
  387. top: var(--scrollHeight--);
  388. }
  389. }
  390. .broadcastDataTopBtmDatacss_bottom {
  391. width: 100%;
  392. animation-name: around_Bottom;
  393. animation-duration: var(--scrollSpeed--);
  394. animation-iteration-count: infinite;
  395. animation-timing-function: linear;
  396. position: absolute;
  397. left: 0;
  398. }
  399. @keyframes around_Bottom {
  400. from {
  401. bottom: 0%;
  402. }
  403. to {
  404. bottom: var(--scrollHeight--);
  405. }
  406. }
  407. .broadcastDataTopBtmDatacss_let {
  408. width: 100%;
  409. animation-name: around_let;
  410. animation-duration: var(--scrollSpeed2--);
  411. animation-iteration-count: infinite;
  412. animation-timing-function: linear;
  413. position: absolute;
  414. left: 0;
  415. top: 0;
  416. }
  417. .animation_pausedcss {
  418. animation-play-state: paused;
  419. }
  420. @keyframes around_let {
  421. from {
  422. left: 0%;
  423. }
  424. to {
  425. left: var(--scrollWidth--);
  426. }
  427. }
  428. .bdbd_item {
  429. padding: 0 12rpx;
  430. line-height: 60rpx;
  431. overflow: hidden;
  432. white-space: nowrap;
  433. text-overflow: ellipsis;
  434. }
  435. @font-face {
  436. font-family: "iconfont";
  437. src: url('//at.alicdn.com/t/font_1686137_9el2ov99ag.eot?t=1589197045289');
  438. /* IE9 */
  439. src: url('//at.alicdn.com/t/font_1686137_9el2ov99ag.eot?t=1589197045289#iefix') format('embedded-opentype'),
  440. /* IE6-IE8 */
  441. url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAANIAAsAAAAAByAAAAL7AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCcAqCJIIbATYCJAMICwYABCAFhG0HNxtIBhHVmxnIfiTYMS7bb8koPCedCeJJj2/e7iZfYqkjkZzk9lw0oCspm5uha1SEYUrOg//lO9IN4UL4FQBGHE6b4vPv8pzmojHnedQFGG8NaG9cCySQAgnMG8ZuIniA2yGAP8kUIg0ateiALwbQTwAZMXRwX3wLLgzGifoi2A1TDbIKC1+1WF0CVvLvy0fKxRcUlgYkthnUcAB13sA47XgOPSgBwXIGwJkFGigEDEiHRlMrtAwVovGPQoZ0OFa2wJs6nkf5h/3jgYDYgMxAABJ1/jMJsPBRMxUARq/vB7iTzgYmPjQ5vv+S6E4b/P2XXBBxLwYELI3pvDFm/XqMs27QknXgrK82yepoddiXOXTJhi3NTe/e7XznTqcNG7ZujLoN2Drexulwy99hXacl0UZCzNW77p1WfV52MOpyx+O3nVuFt1qs+xziN+DL8Q0BU2N17J84FTs1YMOXE/2dXf8DTwV62/5bne0/dmdranzv25uGonfvtepore/p0pXugqw9N2SpuKsuTSuYO7vtjzV1oka1azMqsm50/SYtYxvHNug6blqbRuGpQccDpjYpGzCwauyCmnETJpadjJjwO6teaETz1uHNQjPqfmhPHQC8q/q2Lvj3vyF17cvZvUOqvvkGGAAePO36jTu8q4ZhFvC9Q7PAnxYMzDOxCKjUI/MNs6JfzoECneta8QC2cJ5MVUe9VkzwJerlLD4kZdD4kkk01EJYBFAJG19q4U8BjWcHEME4NGL8gHzmaxBCOQlFMBehCeUy0VAfwyKaz7AJFQ1/OknEkgFki5dUfUYt6MD8IFnaPdKKEtk3DFfVnBdx2gv5TF4Yu6EcXXFHXmLE+Q6TiAfPtMGi7Ya1EhxMGa10UeSY+943XamztDWK+oxa0IH5QbK0e1pcVOXzNwxX1dyRM+J8IZ+pcRi7YQBxle+Dch5ln/MdJhEPnmmDRTNghSGCo7lTRitdnBA45t4o5IfKu+2V298tAfwBGiWwuSZo8KX3YOgfkRnbpgEA') format('woff2'),
  442. url('//at.alicdn.com/t/font_1686137_9el2ov99ag.woff?t=1589197045289') format('woff'),
  443. url('//at.alicdn.com/t/font_1686137_9el2ov99ag.ttf?t=1589197045289') format('truetype'),
  444. /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  445. url('//at.alicdn.com/t/font_1686137_9el2ov99ag.svg?t=1589197045289#iconfont') format('svg');
  446. /* iOS 4.1- */
  447. }
  448. .iconfont {
  449. font-family: "iconfont" !important;
  450. font-size: 16px;
  451. font-style: normal;
  452. -webkit-font-smoothing: antialiased;
  453. -moz-osx-font-smoothing: grayscale;
  454. }
  455. .icon-guangbozheng-:before {
  456. content: "\e640";
  457. }
  458. </style>