在线演示地址:https://www.ewbang.com/community/board.html
本文利用HTML+CSS+JS写了一个简单的弹幕滚动留言板小功能。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="keywords" content="" />
<meta name="description" content="" />
<style>
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
user-select: none;
}
.screen {
overflow: hidden;
position: relative;
height: 100%;
background-repeat: no-repeat;
background-size: 100% 100%;
}
.send {
position: absolute;
bottom: 0;
width: 100%;
height: 80px;
line-height: 80px;
background-color: rgba(10, 10, 10, 0.6);
text-align: center;
}
.input {
position: absolute;
left: 50%;
top: 50%;
margin: -20px -350px;
font-size: 0;
}
.text {
float: left;
width: 600px;
height: 40px;
border: none;
border-radius: 8px 0 0 8px;
}
.s_show div {
position: absolute;
font-size: 18px;
font-weight: bold;
}
.btn {
float: left;
width: 100px;
background-color: orange;
line-height: 40px;
font-size: 18px;
color: #fff;
cursor: pointer;
border-radius: 0 8px 8px 0;
}
html,
body {
margin: 0;
overflow: hidden;
width: 100%;
height: 100%;
cursor: none;
background: black;
background: linear-gradient(to bottom, #000000 0%, #5788fe 100%);
}
.filter {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: #fe5757;
animation: colorChange 30s ease-in-out infinite;
animation-fill-mode: both;
mix-blend-mode: overlay;
}
@keyframes colorChange {
0%,
100% {
opacity: 0;
}
50% {
opacity: 0.9;
}
}
.landscape {
position: absolute;
bottom: 0px;
left: 0;
width: 100%;
height: 100%;
background-size: 1000px 250px;
background-repeat: repeat-x;
background-position: center bottom;
}
</style>
<title>弹幕留言板</title>
</head>
<body>
<div class="screen">
<div class="landscape"></div>
<div class="filter"></div>
<canvas id="canvas"></canvas>
<div class="send">
<div class="input clearfix">
<input type="text" class="text" />
<div class="btn">发送弹幕</div>
</div>
</div>
<div class="s_show">
<div class="magictime twisterInUp">
小狐狸789 :
【跟你谈钱的老板才是好人,跟你谈理想的,都TM不想给你钱!】— 2022-12-28
01:19:37
</div>
<div class="magictime twisterInUp">
小猫999 : 【那些年立下的FLAG自己删了吧,反正也没人记得。】— 2022-11-08
19:39:49
</div>
<div class="magictime twisterInUp">
酷猫000 : 【失眠睡不着,可能是因为,你手机还有电。】— 2023-07-13
00:37:00
</div>
<div class="magictime twisterInUp">
聪明狮子520 : 【过年不吃胖,怎么对得起,死去的鸡鸭鱼猪?】— 2023-04-19
18:28:43
</div>
<div class="magictime twisterInUp">
酷狼789 :
【今天真是幸运的一天,终于实现了身价翻倍,因为猪价又翻了番。】—
2023-01-20 20:37:00
</div>
<div class="magictime twisterInUp">
快乐狗123 : 【你爱不爱你的工作,工作都会在那等你,不离不弃。】—
2023-01-31 23:03:35
</div>
<div class="magictime twisterInUp">
梦幻兔子520 :
【懒是一个很好的托辞,说的好像你勤奋了就能干成大事一样。】— 2023-05-11
15:56:11
</div>
<div class="magictime twisterInUp">
酷鸟789 : 【不要再抑郁下去了孩子,你要像一个,神经病一样活泼开朗。】—
2023-04-12 13:59:07
</div>
<div class="magictime twisterInUp">
勇敢熊000 : 【再努力一点,你就能走向,人生癫疯。】— 2023-05-15
10:25:04
</div>
<div class="magictime twisterInUp">
幸运老虎666 : 【一路上有你,苦一点也愿意,苦很多免谈。】— 2023-03-23
14:18:44
</div>
<div class="magictime twisterInUp">
聪明熊000 : 【怕鬼真的太幼稚了,我带你看看人心。】— 2023-07-02
09:13:57
</div>
<div class="magictime twisterInUp">
幸运狗1314 : 【大家喜欢和你一起,是为了,显示他们的好看。】—
2023-07-18 13:50:43
</div>
<div class="magictime twisterInUp">
酷狗000 : 【要不是生活所迫,谁愿意把自己,弄得一身才华。】— 2023-08-26
07:21:47
</div>
<div class="magictime twisterInUp">
聪明狮子123 : 【攒了一年头皮屑,只为给你下场雪。】— 2023-06-09
17:35:14
</div>
<div class="magictime twisterInUp">
疯狂老虎520 : 【大人只分利弊,小孩才分对错。】— 2023-09-27 18:16:39
</div>
<div class="magictime twisterInUp">
聪明狐狸000 : 【每一个抖腿的人,心里都有一台缝纫机。】— 2022-12-04
05:37:25
</div>
<div class="magictime twisterInUp">
大猫999 :
【小时候最怕梦到自己找厕所,最最可怕的是,人没醒来厕所却找到了。】—
2023-04-15 06:42:35
</div>
<div class="magictime twisterInUp">
幸运狗789 : 【我真是个败家子,上亿的家产,一觉醒来就没了。】—
2023-01-15 12:01:47
</div>
<div class="magictime twisterInUp">
聪明狐狸456 : 【女生之间的友谊啊,就像塑料花,虽然假但永不凋零。】—
2023-08-29 02:51:44
</div>
<div class="magictime twisterInUp">
酷熊888 :
【当你觉得生活对你不公时,秤秤体重,照照镜子,你会觉得一切又合乎情理。】—
2023-09-11 02:50:45
</div>
</div>
</div>
<script>
function Star(id, x, y) {
this.id = id;
this.x = x;
this.y = y;
this.r = Math.floor(Math.random() * 2) + 1;
var alpha = (Math.floor(Math.random() * 10) + 1) / 10 / 2;
this.color = "rgba(255,255,255," + alpha + ")";
}
Star.prototype.draw = function () {
ctx.fillStyle = this.color;
ctx.shadowBlur = this.r * 2;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
ctx.closePath();
ctx.fill();
};
Star.prototype.move = function () {
this.y -= 0.15;
if (this.y <= -10) this.y = HEIGHT + 10;
this.draw();
};
Star.prototype.die = function () {
stars[this.id] = null;
delete stars[this.id];
};
function Dot(id, x, y, r) {
this.id = id;
this.x = x;
this.y = y;
this.r = Math.floor(Math.random() * 5) + 1;
this.maxLinks = 2;
this.speed = 0.5;
this.a = 0.5;
this.aReduction = 0.005;
this.color = "rgba(255,255,255," + this.a + ")";
this.linkColor = "rgba(255,255,255," + this.a / 4 + ")";
this.dir = Math.floor(Math.random() * 140) + 200;
}
Dot.prototype.draw = function () {
ctx.fillStyle = this.color;
ctx.shadowBlur = this.r * 2;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
ctx.closePath();
ctx.fill();
};
Dot.prototype.link = function () {
if (this.id == 0) return;
var previousDot1 = getPreviousDot(this.id, 1);
var previousDot2 = getPreviousDot(this.id, 2);
var previousDot3 = getPreviousDot(this.id, 3);
if (!previousDot1) return;
ctx.strokeStyle = this.linkColor;
ctx.moveTo(previousDot1.x, previousDot1.y);
ctx.beginPath();
ctx.lineTo(this.x, this.y);
if (previousDot2 != false) ctx.lineTo(previousDot2.x, previousDot2.y);
if (previousDot3 != false) ctx.lineTo(previousDot3.x, previousDot3.y);
ctx.stroke();
ctx.closePath();
};
function getPreviousDot(id, stepback) {
if (id == 0 || id - stepback < 0) return false;
if (typeof dots[id - stepback] != "undefined")
return dots[id - stepback];
else return false;
}
Dot.prototype.move = function () {
this.a -= this.aReduction;
if (this.a <= 0) {
this.die();
return;
}
this.color = "rgba(255,255,255," + this.a + ")";
this.linkColor = "rgba(255,255,255," + this.a / 4 + ")";
(this.x = this.x + Math.cos(degToRad(this.dir)) * this.speed),
(this.y = this.y + Math.sin(degToRad(this.dir)) * this.speed);
this.draw();
this.link();
};
Dot.prototype.die = function () {
dots[this.id] = null;
delete dots[this.id];
};
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
WIDTH,
HEIGHT,
mouseMoving = false,
mouseMoveChecker,
mouseX,
mouseY,
stars = [],
initStarsPopulation = 80,
dots = [],
dotsMinDist = 2,
maxDistFromCursor = 50;
setCanvasSize();
init();
function setCanvasSize() {
(WIDTH = document.documentElement.clientWidth),
(HEIGHT = document.documentElement.clientHeight);
canvas.setAttribute("width", WIDTH);
canvas.setAttribute("height", HEIGHT);
}
function init() {
ctx.strokeStyle = "white";
ctx.shadowColor = "white";
for (var i = 0; i < initStarsPopulation; i++) {
stars[i] = new Star(
i,
Math.floor(Math.random() * WIDTH),
Math.floor(Math.random() * HEIGHT)
);
//stars[i].draw();
}
ctx.shadowBlur = 0;
animate();
}
function animate() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i in stars) {
stars[i].move();
}
for (var i in dots) {
dots[i].move();
}
drawIfMouseMoving();
requestAnimationFrame(animate);
}
window.onmousemove = function (e) {
mouseMoving = true;
mouseX = e.clientX;
mouseY = e.clientY;
clearInterval(mouseMoveChecker);
mouseMoveChecker = setTimeout(function () {
mouseMoving = false;
}, 100);
};
function drawIfMouseMoving() {
if (!mouseMoving) return;
if (dots.length == 0) {
dots[0] = new Dot(0, mouseX, mouseY);
dots[0].draw();
return;
}
var previousDot = getPreviousDot(dots.length, 1);
var prevX = previousDot.x;
var prevY = previousDot.y;
var diffX = Math.abs(prevX - mouseX);
var diffY = Math.abs(prevY - mouseY);
if (diffX < dotsMinDist || diffY < dotsMinDist) return;
var xVariation = Math.random() > 0.5 ? -1 : 1;
xVariation =
xVariation * Math.floor(Math.random() * maxDistFromCursor) + 1;
var yVariation = Math.random() > 0.5 ? -1 : 1;
yVariation =
yVariation * Math.floor(Math.random() * maxDistFromCursor) + 1;
dots[dots.length] = new Dot(
dots.length,
mouseX + xVariation,
mouseY + yVariation
);
dots[dots.length - 1].draw();
dots[dots.length - 1].link();
}
function degToRad(deg) {
return deg * (Math.PI / 180);
}
</script>
<script>
//初始化函数
var aShowList = document.querySelectorAll(".s_show div"); //获取元素 H5
var oShow = document.querySelector(".s_show");
var oSend = document.querySelector(".send");
var oBtn = document.querySelector(".btn");
var oText = document.querySelector(".text");
oBtn.onclick = function () {
//鼠标点击事件
var oDiv = document.createElement("div"); //创建div
oDiv.innerHTML = oText.value; //添加弹幕内容
oDiv.className = "magictime twisterInUp"; //弹幕特效
oShow.appendChild(oDiv); //添加一个子节点
init(oDiv); //初始化
oText.value = "";
time = time1;
};
for (var i = 0; i < aShowList.length; i++) {
init(aShowList[i]); //执行初始化函数
}
function init(obj) {
//接受弹幕对象
//确定top值的随机区间
var screenHeight = document.documentElement.clientHeight; //获取屏幕可视高度
var maxTop = screenHeight - oSend.offsetHeight - obj.offsetHeight; //高度差范围
obj.style.top = maxTop * Math.random() + "px";
//控制left值
var screenWidth = document.documentElement.clientWidth; //获取可视宽度
var maxLeft = screenWidth - obj.offsetWidth; //随机宽度差
obj.style.left = maxLeft + "px";
//弹幕的随机颜色
obj.style.color = randomColor();
move(Math.random() * 5 + 1, obj, maxLeft);
}
//弹幕移动函数
function move(k, obj, maxLeft) {
var speed = k; //控制速度的变量
maxLeft -= speed; //往左移动
if (maxLeft > -obj.offsetWidth) {
obj.style.left = maxLeft + "px";
requestAnimationFrame(function () {
move(k, obj, maxLeft);
}); //H5新增的动画函数
} else {
init(obj); //重新初始化 营造循环弹幕效果
}
}
//随机颜色函数
function randomColor() {
return "#" + Math.random().toString(16).slice(-6); //一行简化版截取后六位
}
</script>
</body>
</html>