- 注意:该插件依赖于jQuery
HTML和CSS代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>简单实用文字弹幕</title>
<style type="text/css">
html {
color: #fff;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
background: #cf6a6d;
background: linear-gradient(to right, #f6ad32, #cf6a6d);
}
body {
margin: 0;
min-width: 960px;
}
html, body {
height: 100%;
overflow: hidden;
}
input, button {
border: none;
outline: none;
}
.clearfix::after {
content: '';
height: 0;
display: table;
visibility: hidden;
clear: both;
}
.container {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
.input-box {
position: absolute;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
height: 40px;
padding: 30px 0;
text-align: center;
background: rgba(0,0,0,.6);
}
.input-box input {
width: 320px;
height: 40px;
padding: 0 10px;
font-size: 16px;
border-radius: 10px;
color: #333;
transition: box-shadow .5s;
}
.input-box .btn {
width: 100px;
height: 40px;
line-height: 40px;
margin-left: 10px;
border-radius: 10px;
font-weight: bold;
color: #fff;
font-size: 16px;
background: #cf6a6d;
background: linear-gradient(to right, #f6ad32, #cf6a6d);
cursor: pointer;
transition: box-shadow .5s;
}
.list {
position: absolute;
left: 100%;
white-space: nowrap;
line-height: 32px;
font-size: 18px;
color: #fff;
text-shadow: 0 0 3px #000;
transition: transform 25s linear;
}
.list.animate {
transform: translateX(-3420px);
}
.container .list img {
width: 24px;
height: 24px;
margin-right: 5px;
border-radius: 50%;
vertical-align: text-top;
}
</style>
</head>
<body>
<div class="container" id="container"></div>
<div class="input-box">
<input type="text" maxlength="20" placeholder="说点什么吧~"/>
<button class="btn" id="btn">发送</button>
</div>
<script src="js/jquery-1.10.2.min.js" type="text/javascript" charset="utf-8"></script>
<script src="js/barrageWall.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 实例化弹幕墙
var send = new BarrageWall({
container: '#container',
barrageLen: 10
});
// 发送弹幕
send.upWall('图片路径.png', '小菜基', '发表想法');
// 发送弹幕
$('#btn').click(function () {
var $oIpt = $(this).prev(), // 获取input元素
val = $oIpt.val().trim(); // 获取input值
send.upWall('images/aq.png', '小菜基', val);
$oIpt.val(''); // 清空输入内容
})
// 通过定时器模拟用户输入
var i = 0,
t = null;
t = setInterval(function () {
if (i > 10) {
clearInterval(t);
}
send.upWall('图片路径.png', '小菜基'+ i +'号', '发表个'+ i +'感想.');
i++;
}, 300);
</script>
</body>
</html>
barrageWall.js 代码
;(function () {
var BarrageWall = function (opt) {
this.init(opt);
}
BarrageWall.prototype = {
init: function (opt) {
if (!opt.container) {
throw new Error('必须指定 container 属性,container为弹幕容器的选择器');
}
if (opt.barrageLen < 1) {
throw new Error('必须指定barrageLen属性,barrageLen为弹幕的轨道数');
}
this.container = opt.container; // 弹幕容器
this.barrageLen = opt.barrageLen; // 轨道数
this.lastElem = 0; // 弹幕出现的位置
this.barrage = []; //弹幕墙
this.barrageOffset = []; // 弹幕墙上最后一条弹幕的偏移量
for (var i = 0; i < opt.barrageLen; i++) {
this.barrage.push([])
}
},
upWall: function (img, user, txt) {
this.positionWall(); // 从上至下找出每条弹幕轨道上最后一条弹幕移动位置
var elem = $('<div></div>') // 创建元素
.addClass('list') // 添加样式
.css('top', this.lastElem * 38 + 'px'); // 定位
elem.html('<img src='+ img +' alt="" />'+ user + ':' + txt) // 添加内容
.appendTo(this.container); // 追加在父元素后面
this.barrage[this.lastElem].push(elem); // elem追加在数组中
// 延迟200ms添加动画,防止元素动画不执行
setTimeout(function () {
elem.addClass('animate')
}, 200)
// 25s后动画执行完毕,从数组和页面中移除
setTimeout(function () {
var item,
flag = false;
for (var i = 0; i < this.barrageLen; i++) {
item = this.barrage[i];
if (flag) {
break; // true 跳出循环
}
for (var j = 0; j < item.length; j++) {
if (item[j] === elem) {
this.barrage[i].splice(j, 1);
flag = true;
break; // 满足条件跳出当前循环
}
}
}
elem.remove(); // 移除自己
}, 25000)
},
positionWall: function () {
// 从上至下找出每条弹幕轨道上最后一条弹幕移动位置
var len = this.barrageLen;
for (var i = 0; i <= len; i++) {
if (i === len) { // 弹幕队列超过弹道数进入
this.minOffset()// 弹幕墙上所有的位置都有弹幕且都未出现完毕时,找出他们当中完全最先的那个
} else {
// 找到弹幕出现的位置,找到退出循环
if (this.afterOffset(i)) {
break;
}
}
}
},
afterOffset: function (i) { // 找到弹幕出现的位置
if (this.barrage[i].length === 0) {
this.lastElem = i;
return true;
} else { // 轨道有数据
var elem = this.barrage[i][this.barrage[i].length - 1], // 获取当前弹幕轨道上最后一条弹幕
aboveWidth = elem.width(), // 获取它的宽度
matrix = elem.css('transform'); // 获取它的矩阵值
if (matrix !== 'none') {
var aboveTransform = parseInt(matrix.split(',')[4]); // 取出最后一条弹幕的矩阵值中X轴的偏移量,即translateX
// 50为间隔,为true则表示当前弹幕轨道上最后一条弹幕已经全部出现,则当前弹幕放在该轨道上
if (-aboveTransform - aboveWidth > 50) {
this.lastElem = i;
return true;
}
}
}
return false;
},
minOffset: function () { // 弹幕墙上所有的位置都有弹幕且都未出现完毕时,找出他们当中完全最先的那个
var minOffset = 0,
item;
for (var i = 0; i < this.barrageLen; i++) { // 遍历比较弹幕墙,找出队列最远的那个元素
item = this.barrage[i];
var elem = item[item.length - 1], // 获取当前弹幕轨道上最后一条弹幕
aboveWidth = elem.width(), // 获取它的宽度
matrix = elem.css('transform'); // 获取它的矩阵值
this.barrageOffset[i] = matrix === 'none' ? -aboveWidth : -parseInt(matrix.split(',')[4]) - aboveWidth;
minOffset = this.barrageOffset[i] > this.barrageOffset[minOffset] ? i : minOffset;
}
this.lastElem = minOffset;
}
}
window.BarrageWall = BarrageWall;
})();
如有不足或更好的方式实现,欢迎大家留言探讨
网友评论