<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/jquery.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
.danmu_container_wrap {
width: 100%;
height: 80%;
position: relative;
background: #000;
}
.danmu_container {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.danmu_unit_all {
animation: move 1s linear 5s;
}
.danmu_unit_half {
animation: move_half 1s linear 5s;
-webkit-animation: move_half 1s linear 5s;
}
@keyframes move_half {
0% {
transform: translate(0px, 0px);
}
100% {
left: 0px;
transform: translate(-100%, 0px);
}
}
@keyframes move {
0% {
left: 100%;
transform: translate(0px, 0px);
}
100% {
left: 0px;
transform: translate(-100%, 0px);
}
}
.danmu_container .unit {
position: absolute;
/* width: 100%; */
left: 200%;
display: table;
white-space: nowrap;
}
.danmu_container>.danmu_unit {
left: 100%;
transform: translate(0px, 0px);
}
#control {
margin: 20px;
padding: 8px 20px;
background: #409eff;
color: #fff;
border: 0;
cursor: pointer;
font-size: 16px;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="danmu_container_wrap">
<div class="lines"></div>
<div class="danmu_container"></div>
</div>
<button id="control">暂停</button>
<script>
let DanMu = (function() {
const MAX_AMOUNT = 20;
const MIN_RUNNERS = 20;
let d = {
square: '',
square_high: 0,
roads: 0,
addRunners: 0
};
let r = {
init_all_road: [],
all_road: [],
map_road: {},
runner_idx: []
};
let glo = {
screen_runners_max: 0,
play_count: 0,
runners_play_count: 0
};
let help = {
road_finish: {},
road_finish_runner: {}
};
let fail_queue = [];
let global_time_out = {};
let _init = function(initD) {
d = Object.assign({}, d, initD);
d.square_high = parseFloat(getComputedStyle(d.square).height);
d.roads = (d.square_high / d.road_high) >> 0;
glo.screen_runners_max = d.roads * d.road_per_runner;
for (let i = 0; i < d.roads; i++) {
r.all_road[i] = {
name: i,
runner: {},
amount: 0
};
r.init_all_road[i] = i;
}
if (d.show_lines) {
let _lines = '';
for (let k = 0; k < d.roads; k++) {
_lines += '<div style="height: ' + d.road_high + 'px;line-height:' + d.road_high + 'px;border-bottom: 1px solid #000;box-sizing: border-box;"></div>';
}
document.getElementsByClassName('lines')[0].innerHTML = _lines;
}
(d.stopElementId) && stop_runner_event(d.stopElementId);
d.addRunners = d.runners;
if (d.runners.length < MIN_RUNNERS) {
d.addRunners = shuffle(d.runners.concat(d.runners, d.runners));
}
d.addRunners.forEach(function(unit, i) {
r.map_road[i] = unit;
r.runner_idx.push(i);
});
put_runner_to_road(-1, {});
console.log(d, r);
}
let getRandomInt = function(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
let ranDomColor = function(color) {
if (color && (color.constructor == Array)) {
let index = Math.floor(Math.random() * (color.length))
return color[index];
} else if (color && (color.constructor == String)) {
return color
} else {
return '#' + Math.floor(Math.random() * 0xffffff).toString(16);
}
};
let ranDomSize = function(size) {
if (size && (size.constructor == Array)) {
let index = Math.floor(Math.random() * (size.length))
return size[index] + 'px';
} else if (size && (size.constructor == String)) {
return size + 'px'
} else {
return getRandomInt(16, 26) + 'px'
}
};
let shuffle = function(arr) {
let _arr = arr.slice();
for (let i = 0; i < _arr.length; i++) {
let j = getRandomInt(0, i);
let t = _arr[i];
_arr[i] = _arr[j];
_arr[j] = t;
}
return _arr;
}
let put_runner_to_road = function(roadName, aheadOption) {
if (roadName == -1) {
if (r.init_all_road.length) {
match_road_to_runner(r.init_all_road[0]);
r.init_all_road.splice(0, 1);
put_runner_to_road(-1, {});
}
} else {
match_road_to_runner(roadName, aheadOption);
}
}
let match_road_to_runner = function(roadName, aheadOption) {
let road_data_idx = '';
let roadDatas = r.all_road.filter(function(obj, i) {
if (obj.name == roadName) {
road_data_idx = i;
return obj;
}
});
if (roadDatas && roadDatas.length) {
let road_data = roadDatas[0];
if (road_data && (road_data.amount >= 0)) {
let runner = get_runner();
if (runner) {
road_data.amount++;
road_data.runner[runner.mapNumber] = runner.mapObj;
if (road_data.amount >= d.road_per_runner) {
help.road_finish[roadName] = road_data.amount;
help.road_finish_runner[roadName] = $.extend(true, {}, road_data.runner);
r.all_road.splice(road_data_idx, 1);
}
go_run(roadName, runner.mapObj, aheadOption);
} else {
fail_queue.push({
roadName: roadName,
aheadOption: $.extend({}, aheadOption)
});
}
}
} else {
fail_queue.push({
roadName: roadName,
aheadOption: $.extend({}, aheadOption)
});
}
}
let get_runner = function() {
let runner_idx = r.runner_idx;
let runner_idx_length = runner_idx.length;
if (runner_idx_length > 0) {
glo.runners_play_count++;
glo.play_count = glo.runners_play_count / (glo.screen_runners_max + 1) >> 0;
let map_code = Math.random() * (runner_idx_length) >> 0;
let map_number = runner_idx[map_code];
let map_content = r.map_road[map_number];
let runner = init_runner(map_number, map_content, d.square.querySelector('.unit[has_finish="true"]'));
r.runner_idx.splice(map_code, 1);
return runner;
} else {
return null;
}
}
let init_runner = function(mapNumber, mapContent, $replace) {
let _$div;
if (!$replace) {
_$div = document.createElement('div');
_$div.addEventListener('webkitAnimationEnd', function(ev) {
run_finish(ev);
});
_$div.addEventListener('click', function(ev) {
run_click(ev, d.click_call);
});
d.square.appendChild(_$div);
} else {
_$div = $replace;
}
_$div.setAttribute('class', 'unit');
_$div.setAttribute('has_finish', 'false');
_$div.setAttribute('map_number', mapNumber);
_$div.setAttribute('length', mapContent.split('').length);
_$div.innerHTML = mapContent;
if (_$div.nodeType == 1) {
_$div.setAttribute('width', parseFloat(window.getComputedStyle(_$div).width));
_$div.setAttribute('height', parseFloat(window.getComputedStyle(_$div).height));
}
return {
mapNumber: mapNumber,
mapObj: _$div
};
}
let go_run = function(roadName, $runner, aheadOption) {
let delay = 0;
if (d.road_per_runner < MAX_AMOUNT) {
delay = (1 / Math.sqrt(d.road_per_runner)) * (.5 + ((glo.play_count > 2) ? 1 : Math.min(Math.random(), .5)) * (Math.abs(Math.sin(roadName)) * 2 + Math.random() * 6));
}
let text_length = $runner.getAttribute('length');
let duration = Math.floor(8 + Math.abs(Math.cos(roadName)) * Math.max(text_length, 4) + Math.random() * Math.max(text_length * 1.5, 10));
if (d.duration) {
duration = d.duration;
}
if (d.road_padding) {
$runner.style.top = d.road_padding + (roadName % d.roads) * d.road_high + 'px';
} else {
$runner.style.top = (8 + (roadName % d.roads) * d.road_high + (Math.sin(Math.random() * 50)) * 10) + 'px';
}
$runner.style.color = ranDomColor(d.color)
$runner.style.fontSize = ranDomSize(d.fontsize)
let width = parseFloat(window.getComputedStyle(d.square).width);
let distance = parseFloat($runner.getAttribute('width'));
try {
if (aheadOption.le