mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-26 08:51:20 -08:00
add worker to danmuku
This commit is contained in:
1 parent
5ff4a8f70b
commit
7bcc296fc2
7 files changed
+206
-283
No files matched your search
@@ -1,5 +1,4 @@
|
||||
import { bilibiliDanmuParseFromUrl } from './bilibili';
|
||||
import getDanmuTop from './getDanmuTop';
|
||||
|
||||
export default class Danmuku {
|
||||
constructor(art, option) {
|
||||
@@ -139,6 +138,37 @@ export default class Danmuku {
|
||||
});
|
||||
}
|
||||
|
||||
getEmits() {
|
||||
const result = [];
|
||||
const { clientWidth } = this.$player;
|
||||
const clientLeft = this.getLeft(this.$player);
|
||||
|
||||
this.filter('emit', (danmu) => {
|
||||
const top = danmu.$ref.offsetTop;
|
||||
const left = this.getLeft(danmu.$ref) - clientLeft;
|
||||
const height = danmu.$ref.clientHeight;
|
||||
const width = danmu.$ref.clientWidth;
|
||||
const distance = left + width;
|
||||
const right = clientWidth - distance;
|
||||
const speed = distance / danmu.$restTime;
|
||||
|
||||
const emit = {};
|
||||
emit.top = top;
|
||||
emit.left = left;
|
||||
emit.height = height;
|
||||
emit.width = width;
|
||||
emit.right = right;
|
||||
emit.speed = speed;
|
||||
emit.distance = distance;
|
||||
emit.time = danmu.$restTime;
|
||||
emit.mode = danmu.mode;
|
||||
|
||||
result.push(emit);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
postMessage(message = {}) {
|
||||
return new Promise((resolve) => {
|
||||
message.id = Date.now();
|
||||
@@ -252,7 +282,8 @@ export default class Danmuku {
|
||||
|
||||
update() {
|
||||
const { clientWidth } = this.$player;
|
||||
this.timer = window.requestAnimationFrame(() => {
|
||||
|
||||
this.timer = window.requestAnimationFrame(async () => {
|
||||
if (this.art.playing && !this.isHide) {
|
||||
this.filter('emit', (danmu) => {
|
||||
const emitTime = (Date.now() - danmu.$lastStartTime) / 1000;
|
||||
@@ -263,7 +294,9 @@ export default class Danmuku {
|
||||
}
|
||||
});
|
||||
|
||||
this.getReady().forEach((danmu) => {
|
||||
const readys = this.getReady();
|
||||
for (let index = 0; index < readys.length; index++) {
|
||||
const danmu = readys[index];
|
||||
danmu.$ref = this.getRef();
|
||||
danmu.$ref.innerText = danmu.text;
|
||||
this.$danmuku.appendChild(danmu.$ref);
|
||||
@@ -281,9 +314,23 @@ export default class Danmuku {
|
||||
? this.option.speed / Number(this.art.playbackRate)
|
||||
: this.option.speed;
|
||||
|
||||
const top = getDanmuTop(this, danmu);
|
||||
const target = {
|
||||
mode: danmu.mode,
|
||||
height: danmu.$ref.clientHeight,
|
||||
speed: (clientWidth + danmu.$ref.clientWidth) / danmu.$restTime,
|
||||
};
|
||||
|
||||
if (top !== undefined) {
|
||||
const { top } = await this.postMessage({
|
||||
target,
|
||||
emits: this.getEmits(),
|
||||
antiOverlap: this.option.antiOverlap,
|
||||
clientWidth: this.$player.clientWidth,
|
||||
clientHeight: this.$player.clientHeight,
|
||||
marginBottom: this.marginBottom,
|
||||
marginTop: this.marginTop,
|
||||
});
|
||||
|
||||
if (!this.isStop && top !== undefined) {
|
||||
danmu.$state = 'emit';
|
||||
danmu.$ref.style.visibility = 'visible';
|
||||
|
||||
@@ -308,7 +355,7 @@ export default class Danmuku {
|
||||
this.$refs.push(danmu.$ref);
|
||||
danmu.$ref = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.isStop) {
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
function getData(ins, clientLeft, clientWidth, item) {
|
||||
const top = item.$ref.offsetTop;
|
||||
const left = ins.getLeft(item.$ref) - clientLeft;
|
||||
const height = item.$ref.clientHeight;
|
||||
const width = item.$ref.clientWidth;
|
||||
const distance = left + width;
|
||||
const right = clientWidth - distance;
|
||||
const speed = distance / item.$restTime;
|
||||
const mode = item.mode;
|
||||
const time = item.$restTime;
|
||||
const $ref = item.$ref;
|
||||
|
||||
return {
|
||||
$ref,
|
||||
mode,
|
||||
time,
|
||||
top,
|
||||
left,
|
||||
height,
|
||||
width,
|
||||
right,
|
||||
speed,
|
||||
distance,
|
||||
};
|
||||
}
|
||||
|
||||
export default function getDanmuTop(ins, danmu) {
|
||||
const clientLeft = ins.getLeft(ins.$player);
|
||||
const { clientWidth, clientHeight } = ins.$player;
|
||||
const { antiOverlap } = ins.option;
|
||||
const { marginBottom, marginTop } = ins;
|
||||
const target = getData(ins, clientLeft, clientWidth, danmu);
|
||||
|
||||
const danmus = ins.queue
|
||||
.filter((item) => {
|
||||
return (
|
||||
item.$ref &&
|
||||
item.$state === 'emit' &&
|
||||
item.mode === target.mode &&
|
||||
item.$ref.offsetTop <= clientHeight - marginBottom
|
||||
);
|
||||
})
|
||||
.map((item) => getData(ins, clientLeft, clientWidth, item))
|
||||
.sort((prev, next) => prev.top - next.top);
|
||||
|
||||
if (danmus.length === 0) {
|
||||
return marginTop;
|
||||
}
|
||||
|
||||
danmus.unshift({
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: marginTop,
|
||||
width: clientWidth,
|
||||
speed: 0,
|
||||
distance: clientWidth,
|
||||
});
|
||||
|
||||
danmus.push({
|
||||
top: clientHeight - marginBottom,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: marginBottom,
|
||||
width: clientWidth,
|
||||
speed: 0,
|
||||
distance: clientWidth,
|
||||
});
|
||||
|
||||
for (let index = 1; index < danmus.length; index += 1) {
|
||||
const item = danmus[index];
|
||||
const prev = danmus[index - 1];
|
||||
const prevBottom = prev.top + prev.height;
|
||||
const diff = item.top - prevBottom;
|
||||
if (diff >= target.height) {
|
||||
return prevBottom;
|
||||
}
|
||||
}
|
||||
|
||||
const topMap = [];
|
||||
for (let index = 1; index < danmus.length - 1; index += 1) {
|
||||
const item = danmus[index];
|
||||
if (topMap.length) {
|
||||
const last = topMap[topMap.length - 1];
|
||||
if (last[0].top === item.top) {
|
||||
last.push(item);
|
||||
} else {
|
||||
topMap.push([item]);
|
||||
}
|
||||
} else {
|
||||
topMap.push([item]);
|
||||
}
|
||||
}
|
||||
|
||||
if (antiOverlap) {
|
||||
switch (target.mode) {
|
||||
case 0: {
|
||||
const result = topMap.find((list) => {
|
||||
return list.every((danmu) => {
|
||||
if (clientWidth < danmu.distance) return false;
|
||||
if (target.speed < danmu.speed) return true;
|
||||
const overlapTime = danmu.right / (target.speed - danmu.speed);
|
||||
if (overlapTime > danmu.time) return true;
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
return result && result[0] ? result[0].top : undefined;
|
||||
}
|
||||
case 1:
|
||||
return undefined;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (target.mode) {
|
||||
case 0:
|
||||
topMap.sort((prev, next) => {
|
||||
const nextMinRight = Math.min(...next.map((item) => item.right));
|
||||
const prevMinRight = Math.min(...prev.map((item) => item.right));
|
||||
return nextMinRight * next.length - prevMinRight * prev.length;
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
topMap.sort((prev, next) => {
|
||||
const nextMaxWidth = Math.max(...next.map((item) => item.width));
|
||||
const prevMaxWidth = Math.max(...prev.map((item) => item.width));
|
||||
return prevMaxWidth * prev.length - nextMaxWidth * next.length;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return topMap[0][0].top;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,106 @@
|
||||
function getDanmuTop({ target, emits, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }) {
|
||||
const danmus = emits
|
||||
.filter((item) => item.mode === target.mode && item.top <= clientHeight - marginBottom)
|
||||
.sort((prev, next) => prev.top - next.top);
|
||||
|
||||
if (danmus.length === 0) {
|
||||
return marginTop;
|
||||
}
|
||||
|
||||
danmus.unshift({
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: marginTop,
|
||||
width: clientWidth,
|
||||
speed: 0,
|
||||
distance: clientWidth,
|
||||
});
|
||||
|
||||
danmus.push({
|
||||
top: clientHeight - marginBottom,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: marginBottom,
|
||||
width: clientWidth,
|
||||
speed: 0,
|
||||
distance: clientWidth,
|
||||
});
|
||||
|
||||
for (let index = 1; index < danmus.length; index += 1) {
|
||||
const item = danmus[index];
|
||||
const prev = danmus[index - 1];
|
||||
const prevBottom = prev.top + prev.height;
|
||||
const diff = item.top - prevBottom;
|
||||
if (diff >= target.height) {
|
||||
return prevBottom;
|
||||
}
|
||||
}
|
||||
|
||||
const topMap = [];
|
||||
for (let index = 1; index < danmus.length - 1; index += 1) {
|
||||
const item = danmus[index];
|
||||
if (topMap.length) {
|
||||
const last = topMap[topMap.length - 1];
|
||||
if (last[0].top === item.top) {
|
||||
last.push(item);
|
||||
} else {
|
||||
topMap.push([item]);
|
||||
}
|
||||
} else {
|
||||
topMap.push([item]);
|
||||
}
|
||||
}
|
||||
|
||||
if (antiOverlap) {
|
||||
switch (target.mode) {
|
||||
case 0: {
|
||||
const result = topMap.find((list) => {
|
||||
return list.every((danmu) => {
|
||||
if (clientWidth < danmu.distance) return false;
|
||||
if (target.speed < danmu.speed) return true;
|
||||
const overlapTime = danmu.right / (target.speed - danmu.speed);
|
||||
if (overlapTime > danmu.time) return true;
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
return result && result[0] ? result[0].top : undefined;
|
||||
}
|
||||
case 1:
|
||||
return undefined;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (target.mode) {
|
||||
case 0:
|
||||
topMap.sort((prev, next) => {
|
||||
const nextMinRight = Math.min(...next.map((item) => item.right));
|
||||
const prevMinRight = Math.min(...prev.map((item) => item.right));
|
||||
return nextMinRight * next.length - prevMinRight * prev.length;
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
topMap.sort((prev, next) => {
|
||||
const nextMaxWidth = Math.max(...next.map((item) => item.width));
|
||||
const prevMaxWidth = Math.max(...prev.map((item) => item.width));
|
||||
return prevMaxWidth * prev.length - nextMaxWidth * next.length;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return topMap[0][0].top;
|
||||
}
|
||||
}
|
||||
|
||||
onmessage = (event) => {
|
||||
const { data } = event;
|
||||
|
||||
const top = getDanmuTop(data);
|
||||
self.postMessage({
|
||||
top,
|
||||
id: data.id,
|
||||
test: 'fuck',
|
||||
});
|
||||
};
|
||||
Reference in new issue
Block a user