大三用js写的简单弹幕效果,过去蛮久了,已经不记得当时怎么写的了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
position: relative;
margin: 0 auto;
width: 676px;
height: 380px;
background-color: rgb(228, 225, 222);
}
canvas {
position: absolute;
width: 676px;
height: 380px;
}
button {
display: block;
margin: 10px auto;
width: 60px;
height: 30px;
}
</style>
</head>
<body>
<div>
<canvas></canvas>
</div>
<button align="center">点击</button>
</body>
<script>
var canvas = document.querySelector("canvas")
var button = document.querySelector("button")
var context = canvas.getContext("2d")
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
var frameID = 0
//装填弹幕
var arry = [
{ value: "好看好看", color: "red" }
, { value: "ikun", color: "blue" }
, { value: "我发的", color: "yellow" }
, { value: "氛围", color: "pink" }
, { value: "小黑子", color: "aliceblue" }
, { value: "泰裤了", color: "green" }
, { value: "大哥不能说,要和成为当晚的", color: "cadetblue" }
, { value: "工作好难找啊!", color: "chocolate" }
, { value: "啥都不说", color: "brown" }
, { value: "注释很多自己看", color: "blueviolet" }]
var instan = [null, null, null, null, null, null, null, null, null]//弹幕容量
var hanEnd = [-1, -1, -1, -1]//该行的最后一个
var han = [0, 0, 0, 0]//一行的文字容量最大为:676/20=33个
var Barrage = function () {
this.x //现在的x坐标
this.y //现在的y坐标
this.han //在哪一行
this.moveX //速度
this.value //文本内容
this.color //文本颜色
this.gentime
}
var flag = 0
button.onclick = function () {
if (flag == 0) {
flag = 1
render()
} else {
cancelAnimationFrame(frameID)
flag = 0
}
}
function radomBar() {//随机生成弹幕
var index = parseInt((Math.random() * arry.length))
if (index < arry.length) {
var bar = new Barrage()
bar.value = arry[index].value
bar.color = arry[index].color
bar.x = 676
var hh = randomHan(bar.value)
if (hh == null) { return }
bar.han = hh//0 1 2 3行
bar.y = 28 * (1 + bar.han)
bar.moveX = randomMoveX(bar)
for (var i = 0; i < instan.length; i++) {//
if (instan[i] == null) {
instan[i] = bar
hanEnd[bar.han] = i//谁该行的行尾
break
}
}
}
}
function randomMoveX(bar) {
var moveX = 2
if (hanEnd[bar.han] < 0) {
return moveX
}
//生成了新的bar,那么之前的最后一个,就变成了倒数第二个
//通过这一个计算速度,让他们不会覆盖在一起,1000 / 60 = 16.666
var left = instan[hanEnd[bar.han]].x + instan[hanEnd[bar.han]].value.length * 22//当前倒数第二个左边的距离
var t1 = 16.7 * left / instan[hanEnd[bar.han]].moveX//当前倒数第二个,从现在到移出画布的时间
moveX = (canvas.width * 16.7) / t1//当前最后一个的速度
if (moveX > 4) {//如果速度超过最大速度4,则随机
moveX = 2 + Math.random() * 2
}
return moveX
}
function randomHan() {//随机行
for (var i = 0; i < han.length; i++) {
var index = parseInt(Math.random() * han.length)//随机行
var right = 33 * 20 - han[index]//右边的剩余大小
if (right >= 2 * 20) {//如果改行有剩余空间
return index//返回随机行随机行
}
}
return null
}
var render = function () {// 画布渲染
context.clearRect(0, 0, canvas.width, canvas.height);// 清除画布
radomBar()
draw(instan);// 绘制画布上所有的圆圈圈
frameID = requestAnimationFrame(render);// 继续渲染
};
function draw(a) {
for (var i = 0; i < a.length; i++) {
if (a[i] == null || a[i].value.length <= 0) { continue }
var barrage = a[i]
if (barrage.x < -(barrage.value.length * 20)) {
var tmp = hanEnd.indexOf(i)
if (tmp >= 0) {//更新行尾:这个文字已经移出画布了,如果这个是行尾,重新设为没有行尾
han[barrage.han] = 0
hanEnd[barrage.han] = -1
}
a[i] = null
continue
}
barrage.x = barrage.x - barrage.moveX//更新x坐标
var tmp = hanEnd.indexOf(i)
if (tmp >= 0) {//更新行尾
han[barrage.han] = barrage.x + barrage.value.length * 20
}
context.font = 'bold ' + 20 + 'px "microsoft yahei", sans-serif';
context.fillStyle = barrage.color;
context.fillText(barrage.value, barrage.x, barrage.y);
}
}
</script>
</html>