小程序手持弹幕的原理及实现(uni-app)

本文详细介绍了如何使用uni-app开发一款手持弹幕应用,包括文字横向展示、滚动动画实现以及用户交互功能,如文字输入和滚动速度控制。通过CSS动画和Vue的数据绑定,实现了文字的无缝滚动效果,并允许用户自定义弹幕内容和滚动速度。
摘要由CSDN通过智能技术生成


手持弹幕前言

通过本篇的文章,可以使用HBuilder写一个手持弹幕,一步一步编写出来。(https://download.csdn.net/download/long19981231/85505893?spm=1001.2014.3001.5503)
先来效果展示(小程序)
在这里插入图片描述


一、思路

思考手持弹幕的实现:让文字横屏,然后匀速运动,当文字尾部到达屏幕的一半的时候,手机屏幕的底部再出来和之前一样的文字实现循环,最后用户可以控制文字大小,速度的快慢,文字的颜色等。

二、代码实现

1.文字横向展示

首先需要有个盒子,将盒子设置为和手机屏幕一样的宽高,通过transform属性旋转90度旋转中心点为屏幕的中心
——旋转盒子内容会变吗?
盒子旋转后里面的内容也会跟着改变

旋转后发现文字实现了横向,但是文字位于右上角,需要文字水平居中。给文字的外盒子一个高度百分之百垂直居中。
——这里有个小坑,为啥是高度不是宽度?
原因是盒子旋转了┐( ̄ー ̄)┌

为了看着比较好看点给文字加上filter属性

// template标签
	<view class="barrage-box">
		<view class="bulletB">
			<text>文字横向</text>
		</view>
	</view>

// style标签
	page {
		background: #010101;
	}
	.barrage-box{
		width: 100vh;
		height: 100vw;
		transform-origin: 50vw 50vw;
		transform: rotate(90deg);
		background-color: #010101;
		overflow: hidden;
	}
	.bulletB{
		display: flex;
		align-items: center;
		height: 100%;
		color: #fff;
		font-size: 200rpx;
	}
	.bulletB text {
		filter: drop-shadow(4px 2px 2px #cd2068);
	}

效果图:
手持弹幕

2.让文字滚动起来

这一步就有点复杂,不仅要考虑到那种方式滚动起来更加合理,还要考虑到如何实现连续滚动。
滚动方式采用css动画属性来实现滚动,连续滚动肯定要有两个一样的元素,首先第一个动画文字从屏幕底部滚动到顶部,第二个动画接上第一个动画的结尾,第二个text文字滚动到和顶部一致的时候循环。
——为啥滚动的动画不放到类为bulletB的标签上?
效果不理想,可以试试**(~ ̄▽ ̄)~**
——为啥要用两个动画?
我只能想到用两个动画去实现,如果有更好的方法,指点我一下**(✪ω✪)**

之前没有修改的代码就不显示,新增代码如下:

// template标签
	<view class="bulletB">
		<text :class="rollClass">文字横向~</text>
		<text :class="rollClass">文字横向~</text>
	</view>

// script标签
		data() {
			return {
				rollClass:'',
			}
		},
		onShow() {
			this.roll()
			this.rollClass = 'roll'
		},
		methods: {
			roll(){
			// 这里的2000时间是由于动画执行2s,如果动画时间改变,这个也应该改变
				setTimeout(() => {
					this.roll()
					this.rollClass = 'rollCycle'
				},2000)
			}
		}

// style标签
	.bulletB text {
		padding-right: 300px;
		white-space: nowrap;
		filter: drop-shadow(4px 2px 2px #cd2068);
		animation-duration:2s;
	}
	
	.roll {
		animation-name: rollScreen;
		animation-timing-function: linear
	}
	
	.rollCycle {
		animation-name: roll;
		animation-timing-function: linear;
		animation-iteration-count: infinite;
	}
	
	@keyframes rollScreen {
		0% {
			transform: translateX(100vh);
		}
	
		100% {
			transform: translateX(0px);
		}
	}
	
	@keyframes roll {
		0% {
			transform: translateX(0px);
		}
	
		100% {
			transform: translateX(-100%);
		}
	}

运行界面:
手持弹幕

3.用户可以控制文字

一个输入框用于用户输入,当用户输入完成后,要根据文字的长度去计算出动画所需的时间,重新执行动画。
思路有了开始实现。

之前没有修改的代码就不显示,新增代码如下:

// template标签
		<view v-show="isShow && !isSetup" class="foot">
			<view class="footUp">
				<view class="footUpLeft">
					<input v-model="newRollTxt" type="text" placeholder="请输入内容"/>
					<text @click="setTxt()" class="btn">发送</text>
				</view>
				<!-- <view @click="Setup()" class="footIcon">
					<uni-icons type="settings-filled" size="30" color="#FFFFFF"></uni-icons>
				</view> -->
			</view>
		</view>
		
		<view @click="setShow"  class="barrage-box">
			<view class="bulletB">
				<text :class="rollClass" class="text" :style="{'animation-duration': rollTime}">{{rollTxt}}</text>
				<text :class="rollClass" :style="{'animation-duration': rollTime}">{{rollTxt}}</text>
			</view>
		</view>


// script标签
		data() {
			return {
				rollClass:'',
				rollTxt:'手持弹幕~',
				rollTime:'',
				newRollTxt:'',
				isShow: true, // 底部是否显示
				screenHeight: '', // 屏幕高度
				speed: 300, // 动画速度的比值
				timerName:'' // 定时器
			}
		},
		onReady() {
			uni.getSystemInfo({
				success: (res) => {
					this.screenHeight = res.screenHeight
					this.setTime()
				}
			})
		},
		methods: {
			setShow(){
				this.isShow = !this.isShow
			},
			// 发送弹幕
			setTxt() {
				this.rollTxt = this.newRollTxt
				this.newRollTxt = ''
				// 清除定时器,防止第一次东湖没有执行完,又重新输入了。
				clearTimeout(this.timerName);
				this.setTime()
			},
			// 计算出时间
			setTime() {
				this.$nextTick(() => {
					let txtView = uni.createSelectorQuery().in(this).select(".text");
					txtView.boundingClientRect(
						data => {
							this.rollClass = this.rollClass == 'rollTwo' ? 'roll' : 'rollTwo'
							// 屏幕高度除以动画比值得出第一个动画需要的时间
							let rollSpeed = (this.screenHeight / this.speed).toFixed(1)
							this.rollTime = rollSpeed + 's'
							// 滚动文字长度除以动画比值得出第二循环动画需要的时间
							let rollSpeedTxt = (rollSpeed * (data.height / this.screenHeight)).toFixed(1)
							// 设置一个计时器,当第一个动画结束的时候执行第二个动画
							this.timerName = setTimeout(() => {
								this.rollClass = 'rollCycle'
								this.rollTime = rollSpeedTxt + 's'
							}, rollSpeed * 1000)
						}).exec();
				})
			}
		}


// style标签

	.foot {
		position: fixed;
		bottom: 0rpx;
		z-index: 10;
	}
	
	.footUp {
		padding-left: 30rpx;
		display: flex;
		align-items: center;
		margin-bottom: 20rpx;
	}
	
	.footUpLeft {
		width: 640rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		height: 80rpx;
		padding: 0 30rpx;
		background: #212427;
		color: #FFFFFF;
		border-radius: 10rpx;
	}
	
	.footUpLeft input {
		flex: 1;
	}
	
	.footUpLeft .btn {
		margin-left: 20rpx;
	}

	.rollTwo {
		animation-name: rollAgain;
		animation-timing-function: linear;
	}
	
	@keyframes rollAgain {
		0% {
			transform: translateX(100vh);
		}
	
		100% {
			transform: translateX(0px);
		}
	}


总结

别的小朋友有的我也要有ᕦ(・ㅂ・)ᕤ过程中遇到不少问题,幸运的是都不算是太难。
可能该手持弹幕还有一些问题存在比如文字过短的时候会导致第二个字不是从屏幕最底下出现的,加个文本长度和屏幕长度的对比就好了。
原本还想吧那个修改颜色,速度,大小写上去。明天放假**(~ ̄▽ ̄)~** 就这吧。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

静的小白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值