uniapp+vue3之消息自定义向左滚动(图片加文字)自定义组件,适用多端
效果图
<template>
<view class="l-barrage"> <block v-for="(item,index) in state.items" :key="index"> <view v-if="item.display" class="aon" :style="{top: `${index%2!=0?item.top*27:item.top}rpx`}"> <view class="bbg"> <view class="bbg-flex"> <view class="bbg-flex-item"> <view class="name">{{item.name}}</view> <view>购买了</view> <view class="msg">{{item.msg}}</view> </view> </view> </view> </view> </block> </view> </template> <script setup lang="ts"> import { reactive, getCurrentInstance, } from 'vue' const { proxy } = getCurrentInstance(); let cycle; interface Props { minTime ?: any, maxTime ?: any, minTop ?: any, maxTop ?: any } let props = withDefaults(defineProps<Props>(), { minTime: { type: Number, default: 6 }, maxTime: { type: Number, default: 18 }, minTop: { type: Number, default: 14 }, maxTop: { type: Number, default: 40 } }) const state : any = reactive({ items: [], }) const add = (item, time = Math.ceil(Math.floor(Math.random() * (props.maxTime - props.minTime + 1) + props.minTime))) => { // let op = mathAdd(mathMul(mathAdd(Math.floor(Math.random()*5) , 1),50),100) let op = 3 state.items.push({ msg: item.msg,//奖品名称 time,//时间 top: op,//距离顶部高度 // top: Math.ceil(Math.random() * (this.maxTop - this.minTop + 1) + this.minTop), display: true, name: item.name.length >= 6 ? item.name.substring(0, 5) + '...' : item.name, }); } const emit = defineEmits(['end']) const start = (items = [], type : string) => { state.items = []; cycle && (clearInterval(cycle)); let i = 0, len = items.length; cycle = setInterval(() => { let time = 3; // #ifndef H5 time = Math.ceil(Math.floor(Math.random() * (props.maxTime - props.minTime + 1) + props.minTime)); // #endif if (type == 'onload') { if (i < len) { add(items[i], time); i++; } else { clearInterval(cycle); setTimeout(() => { emit("end", {}); }, time * 1000) } } else { clearInterval(cycle); } }, 2000) } // 第二部:暴露方法 defineExpose({ start, add }) </script> <style lang="scss"> .page { width: 100%; height: 300rpx; } .aon { position: absolute; z-index: 9; white-space: nowrap; animation: mymove 10s linear forwards; animation-timing-function: linear; -webkit-animation-timing-function: linear; animation-fill-mode: forwards; height: 59rpx; padding: 0 1rpx; } @keyframes mymove { from { left: 100%; } to { left: -200%; } } @-moz-keyframes mymove /* Firefox */ { from { left: 100%; } to { left: -200%; } } @-webkit-keyframes mymove /* Safari and Chrome */ { from { left: 100%; } to { left: -200%; } } @-o-keyframes mymove /* Opera */ { from { left: 100%; } to { left: -200%; } } .bbg { width: 432.63rpx; height: 59rpx; border-radius: 89.5rpx; background-color: rgba(0, 0, 0, 0.59); padding-right: 16rpx; font-size: 24rpx; font-weight: 500; color: #fff; .bbg-flex { height: 100%; display: flex; align-items: center; width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; } .bbg-flex-item { display: flex; align-items: center; padding: 0 0 0 25rpx; } } </style>
<template> <barrage ref="lBarrage" @end="getWinActive"></barrage> </template>
const lBarrage = ref<any>(null) const getWinActive = () => { let webList = getWinList(state.recordLength) funcTimer = setTimeout(() => { lBarrage._value.start(webList, 'onload') }, 150) // lBarrage.value.start(webList) } //一次展示几条弹幕 const getWinList = (len : number) => { let webList = [] for (let i = 0; i < len; i++) { let obj = { name: state.orderTwentyLately[i].userNickName, msg: state.orderTwentyLately[i].numeration, top: i, } webList.push(obj) } return webList }