marquee.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  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 class="broadcastTopBtm dsf" :class="[direction=='left'?'broadcastDataTopBtmDatacss_let':direction=='right'?'broadcastDataTopBtmDatacss_rig':'',animation_paused?'animation_pausedcss':'']"
  19. :style="'--scrollWidth--:'+(-scrlloWidth)+'px;--scrollSpeed2--:'+(scrlloWidth)/broadcastStyle.speed+'s;width:'+scrlloWidth*2+'px;'">
  20. <view class="bml01" style="display: flex;justify-content: space-between;">
  21. <slot />
  22. </view>
  23. <view class="" style="display: flex;justify-content: space-between;z-index: 99;">
  24. <slot />
  25. </view>
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. <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;'">
  31. <view v-if="broadcastType=='text'" :class="[direction=='top'?'broadcastDataTopBtmDatacss_top':direction=='bottom'?'broadcastDataTopBtmDatacss_bottom':'',animation_paused?'animation_pausedcss':'']">
  32. <view v-for="(item,index) in broadcastDataTopBtmDataes" :key="index" @click.stop="click_event(index>((broadcastDataTopBtmDataes.length/2)-1)?index-(broadcastDataTopBtmDataes.length/2):index)" class="bdbd_item">
  33. {{item}}
  34. </view>
  35. </view>
  36. <view v-if="broadcastType=='mould'" :class="[direction=='top'?'broadcastDataTopBtmDatacss_top':direction=='bottom'?'broadcastDataTopBtmDatacss_bottom':'',animation_paused?'animation_pausedcss':'']">
  37. <view class="">
  38. <slot />
  39. </view>
  40. <view class="">
  41. <slot />
  42. </view>
  43. </view>
  44. </view>
  45. </view>
  46. </template>
  47. <script>
  48. /**
  49. * author:G.bro
  50. * date:20200513
  51. * * **/
  52. export default {
  53. data() {
  54. return {
  55. broadcastDataes: [],
  56. broadcastDataTopBtmDataes: [],
  57. broadcastStylees: {},
  58. broadcastTopBtmHeight: 0,
  59. scrlloWidth: 0,
  60. animation_paused: false,
  61. qualifications:true
  62. }
  63. },
  64. props: {
  65. broadcastType: {
  66. type: String,
  67. default: 'text' //mould
  68. },
  69. // broadcastDataTopBtmData: {
  70. // type: Array
  71. // },
  72. broadcastData: {
  73. type: Array
  74. },
  75. broadcastStyle: {
  76. type: Object,
  77. default () {
  78. return {
  79. speed: 90, //滚动速度,每秒3个字
  80. font_size: "28", //字体大小(rpx)
  81. text_color: "#fff", //字体颜色
  82. back_color: "#815CD4", //背景色
  83. }
  84. }
  85. },
  86. broadcastIconIsDisplay: { //图标是否显示
  87. type: Boolean,
  88. default: false
  89. },
  90. // broadcast_icon: {
  91. // type: String,
  92. // default: ''
  93. // },
  94. broadcast_tit: {
  95. type: String,
  96. default: '今日热点'
  97. },
  98. direction: {
  99. type: String,
  100. default: 'left'
  101. },
  102. viewHeight: {
  103. type: Number,
  104. default: 200
  105. },
  106. touchEvent: {
  107. type: true,
  108. default: false
  109. }
  110. },
  111. comments: {
  112. },
  113. created() {
  114. if (this.broadcastType == "text") {
  115. if (this.direction == "right" || this.direction == "left") {
  116. this.initial_let_rig();
  117. } else {
  118. let arr = [...this.broadcastData];
  119. arr = arr.concat(arr);
  120. this.broadcastDataTopBtmDataes = arr;
  121. }
  122. }
  123. },
  124. mounted() {
  125. let that = this;
  126. if (this.direction == "top" || this.direction == "bottom") {
  127. const query2 = uni.createSelectorQuery().in(this)
  128. query2.select('.broadcastDataTopBtmDatacss_' + this.direction).boundingClientRect(rect => {
  129. that.broadcastTopBtmHeight = rect.height;
  130. if(that.viewHeight-rect.height>10){
  131. that.qualifications=false;
  132. that.animation_paused = true;
  133. that.broadcastDataTopBtmDataes.splice(that.broadcastDataTopBtmDataes.length/2,that.broadcastDataTopBtmDataes.length-1);
  134. }
  135. console.log(that.broadcastDataTopBtmDataes.length/2, 'that.surplusHeight')
  136. }).exec()
  137. }
  138. if (this.direction == "left" || this.direction == "right") {
  139. if (this.broadcastType == 'mould') {
  140. const query = uni.createSelectorQuery().in(this)
  141. query.select('.bml01').boundingClientRect(rect => {
  142. that.scrlloWidth = rect.width;
  143. // console.log(rect.width, 'that.surplusHeight')
  144. }).exec()
  145. }
  146. // if(this.broadcastType=='text'){有偏差
  147. // let assist = { ...this.broadcastStyle};
  148. // const querys = uni.createSelectorQuery().in(this)
  149. // querys.select('.boradcast_text_left_rig').boundingClientRect(rect => {
  150. // assist.width_mal = rect.width;
  151. // assist.time = rect.width/assist.speed;
  152. // that.broadcastStylees=assist;
  153. // }).exec()
  154. // }
  155. }
  156. },
  157. methods: {
  158. touchendFn(e) {
  159. if (this.touchEvent&&this.qualifications) {
  160. this.animation_paused = false;
  161. }
  162. },
  163. touchstartFn(e) {
  164. if (this.touchEvent&&this.qualifications) {
  165. this.animation_paused = true;
  166. }
  167. },
  168. initial_let_rig() {
  169. let broadcastData = [...this.broadcastData];
  170. console.log(this.direction, 'this.direction')
  171. if (this.direction == "right") {
  172. broadcastData.reverse();
  173. }
  174. let ititdata = broadcastData.map((item) => {
  175. return {
  176. "text": item,
  177. "starspos": uni.getSystemInfoSync().windowWidth - 103
  178. }
  179. }),
  180. assist = { ...this.broadcastStyle
  181. },
  182. this_width = 0,
  183. spacing = 0,
  184. speed = (assist.speed * assist.font_size); //m每秒行走的距离
  185. for (let i in ititdata) {
  186. this_width += ititdata[i].text.length * assist.font_size;
  187. if (i != ititdata.length - 1) {
  188. spacing += ititdata[i].starspos
  189. }
  190. }
  191. let total_length = (this_width / 2) + spacing; //总长
  192. assist.time = total_length / speed; /**滚动时间*/
  193. assist.width_mal = total_length;
  194. this.broadcastDataes = ititdata;
  195. this.broadcastStylees = assist;
  196. },
  197. click_event(index){
  198. this.$emit("changeEvent",{index,msg:`你点击了${index+1}条`});
  199. }
  200. }
  201. }
  202. </script>
  203. <style>
  204. /* page {
  205. overflow: hidden;
  206. width: 100%;
  207. } */
  208. .marquee_box {
  209. width: 100%;
  210. overflow: hidden;
  211. position: inherit;
  212. height: auto;
  213. }
  214. .mould {
  215. width: 750rpx;
  216. overflow: hidden;
  217. position: inherit;
  218. }
  219. .dsf {
  220. display: flex;
  221. justify-content: space-between;
  222. }
  223. .broadIcon {
  224. /* width: 60rpx; */
  225. padding: 0 22rpx;
  226. height: 60rpx;
  227. display: flex;
  228. justify-content: center;
  229. align-items: center;
  230. position: absolute;
  231. left: 0;
  232. top: 0;
  233. color: #fff;
  234. z-index: 999;
  235. line-height: 60rpx;
  236. }
  237. .marquee_container {
  238. position: relative;
  239. width: 100%;
  240. height: 60rpx;
  241. }
  242. .marquee_text_left {
  243. display: flex;
  244. white-space: nowrap;
  245. animation-name: around_left;
  246. animation-duration: var(--speed--);
  247. animation-iteration-count: infinite;
  248. animation-timing-function: linear;
  249. line-height: 60rpx;
  250. position: absolute;
  251. }
  252. @keyframes around_left {
  253. from {
  254. left: 100%;
  255. }
  256. to {
  257. left: var(--marqueeWidth--);
  258. }
  259. }
  260. .marquee_text_right {
  261. display: flex;
  262. white-space: nowrap;
  263. animation-name: around_right;
  264. animation-duration: var(--speed--);
  265. animation-iteration-count: infinite;
  266. animation-timing-function: linear;
  267. line-height: 60rpx;
  268. position: absolute;
  269. }
  270. @keyframes around_right {
  271. from {
  272. right: 100%;
  273. }
  274. to {
  275. right: var(--marqueeWidth--);
  276. }
  277. }
  278. .marquee_tit {
  279. height: 60rpx;
  280. line-height: 60rpx;
  281. }
  282. .broadcastTopBtm {
  283. padding: 12rx;
  284. overflow: hidden;
  285. position: relative;
  286. }
  287. .broadcastDataTopBtmDatacss_top {
  288. width: 100%;
  289. animation-name: around_top;
  290. animation-duration: var(--scrollSpeed--);
  291. animation-iteration-count: infinite;
  292. animation-timing-function: linear;
  293. position: absolute;
  294. left: 0;
  295. }
  296. @keyframes around_top {
  297. from {
  298. top: 0%;
  299. }
  300. to {
  301. top: var(--scrollHeight--);
  302. }
  303. }
  304. .broadcastDataTopBtmDatacss_bottom {
  305. width: 100%;
  306. animation-name: around_Bottom;
  307. animation-duration: var(--scrollSpeed--);
  308. animation-iteration-count: infinite;
  309. animation-timing-function: linear;
  310. position: absolute;
  311. left: 0;
  312. }
  313. @keyframes around_Bottom {
  314. from {
  315. bottom: 0%;
  316. }
  317. to {
  318. bottom: var(--scrollHeight--);
  319. }
  320. }
  321. .broadcastDataTopBtmDatacss_let {
  322. width: 100%;
  323. animation-name: around_let;
  324. animation-duration: var(--scrollSpeed2--);
  325. animation-iteration-count: infinite;
  326. animation-timing-function: linear;
  327. position: absolute;
  328. left: 0;
  329. top: 0;
  330. }
  331. .animation_pausedcss {
  332. animation-play-state: paused;
  333. }
  334. @keyframes around_let {
  335. from {
  336. left: 0%;
  337. }
  338. to {
  339. left: var(--scrollWidth--);
  340. }
  341. }
  342. .bdbd_item {
  343. padding: 0 12rpx;
  344. line-height: 60rpx;
  345. overflow: hidden;
  346. white-space: nowrap;
  347. text-overflow: ellipsis;
  348. }
  349. @font-face {
  350. font-family: "iconfont";
  351. src: url('//at.alicdn.com/t/font_1686137_9el2ov99ag.eot?t=1589197045289');
  352. /* IE9 */
  353. src: url('//at.alicdn.com/t/font_1686137_9el2ov99ag.eot?t=1589197045289#iefix') format('embedded-opentype'),
  354. /* IE6-IE8 */
  355. 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'),
  356. url('//at.alicdn.com/t/font_1686137_9el2ov99ag.woff?t=1589197045289') format('woff'),
  357. url('//at.alicdn.com/t/font_1686137_9el2ov99ag.ttf?t=1589197045289') format('truetype'),
  358. /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  359. url('//at.alicdn.com/t/font_1686137_9el2ov99ag.svg?t=1589197045289#iconfont') format('svg');
  360. /* iOS 4.1- */
  361. }
  362. .iconfont {
  363. font-family: "iconfont" !important;
  364. font-size: 16px;
  365. font-style: normal;
  366. -webkit-font-smoothing: antialiased;
  367. -moz-osx-font-smoothing: grayscale;
  368. }
  369. .icon-guangbozheng-:before {
  370. content: "\e640";
  371. }
  372. </style>