uni-app使用canvas技术实现弹幕(思路+代码)

这篇博客详细介绍了如何在uni-app中实现一个弹幕展示功能。首先,通过Object.assign处理接口返回的数据,添加速度和坐标属性。接着,创建canvas绘制区域,利用requestAnimationFrame实现动画效果,使弹幕内容从画布右侧进入并以不同速度滚动到左侧。同时,通过调整y轴间距确保多条弹幕的展示。最后,展示了具体的代码实现,包括数据整理和绘制过程。
摘要由CSDN通过智能技术生成

之前在公司有一个项目,需要使用uni-app实现一个弹幕的效果,展示已付款用户。

当时项目赶时间,使用了一个插件,后来琢磨了一下实现思路:

分析

一个弹幕功能,首先需要拿到弹幕内容,这个不用多说。

除此以外,还要有画布的总宽度,让数据一开始处于画布区域之外。

在这里插入图片描述
然后让数据以不同的速度,向canvas区域内容滑动,知道完全穿过这个canvas区域。

当然数据不会只有一条,所以还要设置y轴的间距,如图所示:

在这里插入图片描述

实现思路

整理数据

接口中返回的数据,一般只包含弹幕内容,所以速度和x轴,y轴这些属性,只能靠前端自己对数据做进一步处理。

例如接口提供的信息如下:

data(){
	return {
		bullet:[
			{bullet:"弹幕内容1"},
			{bullet:"弹幕内容2"},
			{bullet:"弹幕内容3"},
			...
		]
	}	
}

而我们需要的数据格式却应该是

data(){
	return {
		bullet:[
			{bullet:"弹幕内容1",speed:Math.random()*1+1,x:画布宽度,y:随机高度},
			{bullet:"弹幕内容2",speed:Math.random()*1+1,x:画布宽度,y:随机高度},
			{bullet:"弹幕内容3",speed:Math.random()*1+1,x:画布宽度,y:随机高度},
			...
		]
	}	
}

这里我使用了Object.assign去合并数据

this.bullet = this.bullet.map(item=>{
    return Object.assign(item,{
        speed:Math.random()*1+1,
        x: 750,
        y: Math.random()*100+20
        }
    )
})

绘制

创建canvas绘制箱

const ctx = uni.createCanvasContext("bulletCanvas")

绘制前清空整个画布

ctx.clearRect(0,0,750,300)

因为有多个bullet内容,所以首先考虑的是循环绘制,将每个循环到的内容配置进去。

考虑到移动端性能参差不齐,所以配合requestAnimationFrame来实现动画。

this.bullet.forEach(item=>{
	// 绘制文字内容及位置
	ctx.fillText(item.bullet,item.x,item.y)
	// 每次达到渲染频率,就让x轴向左移动一段随机的宽度,即速度
	item.x -= item.speed
	// 调用measureText()来获取TextMertics对象
	let textMertics = ctx.measureText(item.bullet)
	// 根据TextMertics对象获取文字宽度
	let textWidth = textMertics.width
	// 当弹幕内容滚动到画布之外的时候,让其再次回到右边
	if(item.x<-textWidth){
		item.x = 750
	}
})

演示代码

<template>
	<view class="cart">
		<view class="bullet">
			<canvas style="width:750rpx;height:300rpx" canvas-id="bulletCanvas"></canvas>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				bullet:[
					{bullet:"内容1"},
					{bullet:"内容1"},
					{bullet:"内容1"},
					{bullet:"内容1"},
					{bullet:"内容1"},
					{bullet:"内容1"},
					{bullet:"内容1"},
					{bullet:"内容1"},
					{bullet:"内容1"}
				]
			}
		},
		onLoad() {
		},
		onReady() {
			this.order()
			.then(()=>{
				this.draw()
			})
		},
		methods: {
			// 整理数据
			order(){
				return new Promise((resolve,reject)=>{
					resolve(
						this.bullet = this.bullet.map(item=>{
							return Object.assign(item,{
								speed:Math.random()*1+1,
								x: 750,
								y: Math.random()*100+20
							})
						})
					)
				})
			},
			draw(){
				const ctx = uni.createCanvasContext("bulletCanvas")
				
				function anim(){
					ctx.setFontSize(20)
					// 擦除整个画布
					ctx.clearRect(0,0,750,300)
					// 循环绘制
					this.bullet.forEach(item=>{
						ctx.fillText(item.bullet,item.x,item.y)
						item.x -= item.speed
						// 调用measureText()来获取TextMertics对象
						let textMertics = ctx.measureText(item.bullet)
						// 根据TextMertics对象获取文字宽度
						let textWidth = textMertics.width
						// 当弹幕滚动到画布之外的时候,再次回到右边
						if(item.x<-textWidth){
							item.x = 750
						}
					})
					ctx.draw()
					requestAnimationFrame(anim.bind(this))
				}
				anim.call(this)
			}
		}
	}
</script>

<style>
</style>

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知猪狭

恰饭恰饭

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

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

打赏作者

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

抵扣说明:

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

余额充值