marquee.vue 11 KB

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