Files
taimed/uni_modules/yingbing-video/static/html/dist/yb-player-danmu.js
chenghuan 0e900d19be feat: 集成edu-core模块并重构课程详情页视频播放
- 添加edu-core本地依赖,用于视频播放组件
- 重构课程详情页,使用CourseVideo组件替换原有视频播放逻辑
- 优化课程列表页布局和样式,修复边框单位问题
- 更新manifest.json支持多方向屏幕旋转
2026-02-09 10:29:59 +08:00

671 lines
26 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var YbDanmu = /*#__PURE__*/function () {
function YbDanmu(container, data) {
var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
_classCallCheck(this, YbDanmu);
this.container = typeof container == 'string' ? document.querySelector(container) : container;
this.config = _objectSpread(_objectSpread({}, YbDanmu.DEFAULT_CONFIG), config);
this.data = data;
this.filter = new YbDanmuFilter(this.config.filter); //过滤规则
this.list = this._filterData(data);
this.runline = []; //正在跑动的弹幕列表
this.canvas = null; //canvas元素
this.ctx = null; //canvas实例
this.paused = true; //是否暂停
this.currentTime = 0; //当前时间轴
this._animation = null; //动画实例
}
return _createClass(YbDanmu, [{
key: "load",
value:
//加载弹幕
function load() {
if (this.container) {
var canvas = document.createElement('CANVAS');
this.container.appendChild(canvas);
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.updateSize();
}
}
//卸载弹幕
}, {
key: "unload",
value: function unload() {
this._clearAnimationFrame();
this.list = [];
this.runline = [];
if (this.ctx) this.ctx = null;
if (this.canvas) {
this.canvas.remove();
this.canvas = null;
}
}
//更新数据
}, {
key: "setData",
value: function setData(data) {
this.data = data;
this.reset();
}
//动态配置
}, {
key: "setConfig",
value: function setConfig(key, value) {
this.config[key] = value;
}
//播放弹幕
}, {
key: "play",
value: function play() {
this.paused = false;
this._render();
}
//暂停弹幕
}, {
key: "pause",
value: function pause() {
this._clearAnimationFrame();
this.paused = true;
}
//跳转弹幕
}, {
key: "seek",
value: function seek(time) {
this.currentTime = time;
this.reset();
}
//更新时间轴(需要外部更新时间轴否则弹幕不会运行)
}, {
key: "time",
value: function time(_time) {
var _this = this;
//计算本次更新时间和上次时间的时间差
var diffrenece = _time - this.currentTime;
//记录新时间
this.currentTime = _time;
//新列表
var newList = [];
//跑动列表
var runline = [];
//循环弹幕列表
this.list.forEach(function (danmu) {
//当前时间减去弹幕显示时间
var range = _this.getCurrentTime() - danmu.time;
//获取当前时间和上次时间的时间差以内的弹幕
if (range >= 0 && range < Math.abs(diffrenece)) runline.push(danmu);
//记录不在范围内的弹幕
else newList.push(danmu);
});
//去掉已经渲染的弹幕
this.list = newList;
//计算需要渲染弹幕的布局
for (var i = 0; i < runline.length; i++) {
var bar = this._layout(runline[i]);
if (bar) this.runline.push(bar);
}
//排序弹幕
this.runline.sort(function (a, b) {
return a.time - b.time;
});
}
//清空画布
}, {
key: "clear",
value: function clear() {
this.ctx && this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
}
//显示弹幕舞台
}, {
key: "show",
value: function show() {
this.container.style.visibility = 'visible';
}
//隐藏弹幕舞台
}, {
key: "hide",
value: function hide() {
this.container.style.visibility = 'hidden';
}
//更新尺寸
}, {
key: "updateSize",
value: function updateSize() {
var width = this.container.offsetWidth;
var height = this.container.offsetHeight;
var dpr = this.config.accuracy == 'auto' ? window.devicePixelRatio : this.config.accuracy;
this.canvas.width = width * dpr;
this.canvas.height = height * dpr;
this.canvas.style.width = width;
this.canvas.style.height = height;
this.ctx.scale(dpr, dpr);
}
//重置数据和画布
}, {
key: "reset",
value: function reset() {
var _this2 = this;
this.clear();
this.list = this._filterData(this.data);
this.runline = [];
var duration = this.canvas.offsetWidth / (this.config.speed * this.config.playbackRate) / 60; //滚动周期除以60是因为为大概每秒60帧根据滚动周期去获取可能出现在屏幕上的弹幕
var newList = [];
var runline = [];
this.list.forEach(function (danmu) {
var range = _this2.getCurrentTime() - danmu.time;
//重置数据的时候,考虑到播放进度可能在中间,未避免弹幕丢失,将时间误差控制在滚动周期以内
if (range >= 0 && range < duration) runline.push(danmu);
//记录不在范围内的弹幕
else newList.push(danmu);
});
//去掉已经渲染的弹幕
this.list = newList;
//计算渲染弹幕的布局
for (var i = 0; i < runline.length; i++) {
var bar = this._layout(runline[i]);
if (bar) this.runline.push(bar);
}
this.runline.sort(function (a, b) {
return a.time - b.time;
}); //排序弹幕
}
}, {
key: "refresh",
value: function refresh() {
this.updateSize();
this.reset();
}
//弹幕是否正在显示
}, {
key: "getVisible",
value: function getVisible() {
var _this$container$style;
return this.container ? ((_this$container$style = this.container.style) === null || _this$container$style === void 0 ? void 0 : _this$container$style.visibility) == 'visible' : false;
}
//获取时间进度
}, {
key: "getCurrentTime",
value: function getCurrentTime() {
return this.currentTime + this.config.timeDiffrence; //加上时间差
}
/**
* 发送弹幕
* @param {Object} danmu 弹幕数据
* @param {Boolean}border 使用边框
*/
}, {
key: "send",
value: function send(danmu, border) {
this.data.push(danmu);
this.runline.push(this._layout(_objectSpread(_objectSpread({}, danmu), {}, {
time: danmu.time + this.config.timeDiffrence
}), border, true)); //强制显示弹幕
}
//插入弹幕数据,但不会渲染
}, {
key: "insert",
value: function insert(danmu) {
this.data.push(danmu);
this.list.push(danmu);
}
//渲染弹幕
}, {
key: "_render",
value: function _render() {
var _this3 = this;
this._clearAnimationFrame();
if (this.paused) return;
if (this.runline.length) {
this.clear();
for (var i = 0; i < this.runline.length; i++) {
var b = this.runline[i];
//移除渲染完毕的弹幕
if (b.left + b.width <= 0 || b.boxWidth <= 0) {
this.runline.splice(i, 1);
i--;
continue;
}
// b.speed = this._detectionBump(b);//碰撞检测,保留位置,可能不需要
var speed = (this.config.speed + b.speed) * this.config.playbackRate; //弹幕随机的速度加上默认设置速度再乘以倍速,才是真正移动的速度
if (b.mode == 1 || !b.mode) b.left -= speed; //滚动弹幕将x轴位置减去速度实现滚动动画
else b.boxWidth -= speed; //顶端和底端弹幕,将记录的画布宽度减去速度,实现渲染时长
//非滚动弹幕当boxWidth大于画布宽度时则不绘制避免弹幕提前出现
if (b.mode == 1 || !b.mode || b.boxWidth <= this.canvas.offsetWidth) this._drawText(b);
}
}
this._animation = window.requestAnimationFrame(function () {
return _this3._render();
});
}
/**
* 计算弹幕布局
* @param { Object|String } danmu 弹幕对象
* @param {Boolean} border 是否使用边框
* @param {Boolean} force 是否强制显示
*/
}, {
key: "_layout",
value: function _layout(danmu, border, force) {
var ctx = this.ctx;
var canvas = this.canvas;
var config = this.config;
var boxWidth = canvas.offsetWidth;
var fontSize = danmu.fontSize || config.fontSize;
var fontFamily = danmu.fontFamily || config.fontFamily;
var fontScale = config.fontScale;
var color = danmu.color || config.color;
var mode = danmu.mode || 1;
var text = danmu.text;
var time = danmu.time;
ctx.font = "".concat(fontSize * fontScale, "px ").concat(fontFamily); //设置字体大小和样式
var width = Math.ceil(ctx.measureText(text).width); //测算文本宽度
var speed = mode == 1 ? Math.random() * 0.1 : 0; //随机移动速度(弹幕一帧移动的距离,加上随机数,可以让弹幕滚动更加有层次感)
var offset = (this.getCurrentTime() - time) * 60 * (config.speed + speed); //根据弹幕出现时间和当前时间轴的时间差,计算弹幕的初始偏移值
var left = mode == 1 ? boxWidth - offset : boxWidth / 2 - width / 2; //获取弹幕x轴位置
var track = this._getTrack(fontSize, mode, offset, force); //获取弹幕y轴位置
var top = track.top;
if (top > -1) {
return {
mode: mode,
text: text,
time: time,
fontSize: fontSize,
color: color,
top: top,
left: left,
speed: track.isOverlap ? speed + 2 + Math.random() * 0.5 : speed,
//如果是重叠的弹幕则加快速度,避免一直重叠,这样观感不好
width: width,
boxWidth: boxWidth - offset,
//顶部和底部弹幕的显示时间根据舞台宽度和移动速度决定
border: border //自己发送的弹幕需要加上边框,作区别显示
};
}
return false;
}
/**
* 绘制文字
* @param {Object} danmu 弹幕对象
* @param {String} mode 弹幕模式 1-滚动 4-底部 5-顶部
*/
}, {
key: "_drawText",
value: function _drawText(danmu) {
var mode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
var ctx = this.ctx;
var config = this.config;
if (ctx) {
ctx.beginPath();
var fontSize = danmu.fontSize || config.fontSize;
var fontFamily = danmu.fontFamily || config.fontFamily;
var color = danmu.color || config.color;
var opacity = config.opacity;
var fontScale = config.fontScale;
var newFontSize = fontSize * fontScale;
ctx.font = "".concat(fontSize * fontScale, "px ").concat(fontFamily);
ctx.strokeStyle = YbDanmu.colorToRgba(YbDanmu.getStrokeColor(color), opacity);
ctx.strokeText(danmu.text, danmu.left, danmu.top);
ctx.fillStyle = YbDanmu.colorToRgba(color, opacity);
ctx.fillText(danmu.text, danmu.left, danmu.top);
if (danmu.border) {
//如果带边框
ctx.strokeStyle = color; //边框颜色
ctx.lineWidth = 2; //边框宽度
ctx.strokeRect(danmu.left, danmu.top - newFontSize, danmu.width, newFontSize + config.lineGap); //绘制边框
}
ctx.closePath();
}
}
/**
* 计算弹幕应该放在哪条轨道
* @param fontSize弹幕字体大小
* @param mode弹幕模式1-滚动 4-底部 5-顶部
* @param offset弹幕初始x轴位置偏差值
* @param force是否强制显示用于弹幕发送
*/
}, {
key: "_getTrack",
value: function _getTrack(fontSize) {
var mode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var force = arguments.length > 3 ? arguments[3] : undefined;
//canvas绘制文字x,y坐标是按文字左下角计算预留30px
var canvas = this.canvas;
var isOverlap = false; //是否重叠
var nowTop = -1; //最终返回的顶部距离
var minLen = -1; //最小弹幕数量
var minTop = -1; //最小弹幕数量轨道
var boxWidth = canvas.offsetWidth;
var boxHeight = canvas.offsetHeight;
var config = this.config;
var lineGap = config.lineGap;
var top = config.top;
var bottom = config.bottom;
var fontScale = config.fontScale;
var newFontSize = fontSize * fontScale;
var reserve = 5; //画布预留位置(给画布底部流出一段距离)不预留可能导致最后一个轨道的弹幕显示不全
var trackLen = Math.floor((boxHeight - top - bottom) / (newFontSize + lineGap)); //计算轨道数量
var tracks = [];
if (mode == 4) {
//弹幕模式为底端,从底部开始加载,所以要用画布高度减去轨道高度,才是底端弹幕渲染的轨道高度
for (var i = 0; i < trackLen; i++) tracks.push(boxHeight - (i * newFontSize + i * lineGap + top + reserve)); //排列轨道
} else {
for (var _i = 0; _i < trackLen; _i++) tracks.push((_i + 1) * newFontSize + _i * lineGap + top); //排列轨道
}
for (var _i2 = 0; _i2 < tracks.length; _i2++) {
var trackTop = tracks[_i2];
//当前轨道上有多少条弹幕
var danmus = this.runline.filter(function (danmu) {
return danmu.top < trackTop + newFontSize && danmu.fontSize * fontScale + danmu.top > trackTop && danmu.mode == mode;
});
if (danmus.length < minLen || minLen == -1) {
//获取最少弹幕数量的轨道
minLen = danmus.length;
minTop = trackTop;
}
if (danmus.length == 0) {
//当前轨道没有弹幕运行,直接插入该轨道
nowTop = trackTop;
break;
} else {
if (danmus.length > 0 && mode == 1) {
//当前轨道有弹幕运行,且弹幕模式是滚动模式时
var arr = danmus.map(function (danmu) {
return danmu.left + danmu.width;
});
var max = Math.max.apply(Math, _toConsumableArray(arr)); //获取当前轨道最右的弹幕
//如果当前轨道还有空位则将弹幕放入当前轨道
if (max < boxWidth - offset - 10) {
//预留10像素间隔
nowTop = trackTop;
break;
}
}
}
}
if (nowTop == -1 && (!config.overlap || force)) {
//没有找到可插入的轨道,但没有开启防重叠或者需要强制显示弹幕,这个弹幕弹幕会无视原来的弹幕开启新的弹幕墙
nowTop = minTop; //将弹幕强制插入最少弹幕数量的轨道
isOverlap = true; //重叠弹幕
}
return {
top: nowTop + top,
//加上上边距top
isOverlap: isOverlap
};
}
//过滤数据
}, {
key: "_filterData",
value: function _filterData(data) {
var _this4 = this;
var config = this.config;
var disableScroll = config.disableScroll;
var disableTop = config.disableTop;
var disableBottom = config.disableBottom;
return YbPlayer.deepClone(data.filter(function (item) {
return (item.mode != 1 || !disableScroll) && (item.mode != 5 || !disableTop) && (item.mode != 4 || !disableBottom) && !_this4.filter.filter(item.text);
}));
}
}, {
key: "_clearAnimationFrame",
value: function _clearAnimationFrame() {
if (this._animation) {
window.cancelAnimationFrame(this._animation);
this._animation = null;
}
}
}], [{
key: "parseBiliXml",
value:
//格式化b站XML文件弹幕
function parseBiliXml(content) {
var pattern = /<d\b[^>]*>(.*?)<\/d\s*>/g;
var danmuku = [];
var match = '';
while ((match = pattern.exec(content)) !== null) {
var attr = match[0].match(/p=\"*([\s\S]*?)\"/)[1];
var attrs = attr.split(',');
danmuku.push({
mode: attrs[1],
time: Number(attrs[0]),
color: YbDanmu.decimalToRgb(Number(attrs[3])),
fontSize: attrs[2],
text: match[1]
});
}
return danmuku;
}
//格式化b站ssa文件弹幕
}, {
key: "parseBiliSsa",
value: function parseBiliSsa(content) {
var lines = content.split('\n');
var events = [];
var currentSection;
lines.forEach(function (line) {
line = line.trim();
if (line.startsWith('[') && line.endsWith(']')) {
currentSection = line.slice(1, -1).toLowerCase();
return;
}
if (currentSection === 'events') {
if (line.toLowerCase().startsWith('format:')) {
// 解析事件格式行
var format = line.slice(7).split(',').map(function (item) {
return item.trim().toLowerCase();
});
// 存储事件格式定义
} else if (line.toLowerCase().startsWith('dialogue:')) {
// 解析对话行
var dialogueValues = line.slice(10).split(',').map(function (item) {
return item.trim();
});
// 注意:文本部分可能包含逗号,所以不能简单分割
var textIndex = 9; // 根据format文本通常是第9个字段从0开始计数
var text = dialogueValues.slice(9).join(','); // 合并文本部分
var dialogueData = {
start: dialogueValues[1],
end: dialogueValues[2],
style: dialogueValues[3],
text: text
};
events.push(dialogueData);
}
}
});
return events.filter(function (e) {
return !e.text.includes('\\a5\\pos');
}).map(function (e) {
var style = e.text.match(/\{*([\s\S]*?)\}/)[1];
var arr = style.split('\\');
return {
mode: 1,
time: timeToSeconds(e.start),
color: arr[2].replace('c&H', '#'),
fontSize: arr[3].replace('fs', ''),
text: e.text.replace(/\{.*?\}/g, '')
};
});
}
//根据文字颜色自动生成反色边框
}, {
key: "getStrokeColor",
value: function getStrokeColor(color) {
var r, g, b;
if (color.startsWith('#')) {
color = color.length == 7 ? color : '#' + color.slice(1, 4) + color.slice(1, 4);
r = parseInt(color.slice(1, 3), 16);
g = parseInt(color.slice(3, 5), 16);
b = parseInt(color.slice(5, 7), 16);
}
if (color.startsWith('rgb')) {
var match = color.match(/rgb\(*([\s\S]*?)\)/);
var colors = match[1].split(',');
r = colors[0];
g = colors[1];
b = colors[2];
}
var $grayLevel = r * 0.299 + g * 0.587 + b * 0.144 / 255;
//判断是否是深色
if ($grayLevel < 0.5) return '#ffffff';else return '#000000';
}
}, {
key: "colorToRgba",
value: function colorToRgba(color, opacity) {
if (color.startsWith('#')) {
color = color.length == 7 ? color : '#' + color.slice(1, 4) + color.slice(1, 4);
var _str = "rgba(";
var _r = parseInt(color.slice(1, 3), 16).toString();
var _g = parseInt(color.slice(3, 5), 16).toString();
var _b = parseInt(color.slice(5, 7), 16).toString();
_str += _r + "," + _g + "," + _b + "," + opacity + ")";
return _str;
}
if (color.startsWith('rgb')) {
var str = "rgba(";
var match = color.match(/rgb\(*([\s\S]*?)\)/);
var colors = match[1].split(',');
var r = colors[0];
var g = colors[1];
var b = colors[2];
str += r + "," + g + "," + b + "," + opacity + ")";
return str;
}
}
//16进制转rgb
}, {
key: "decimalToRgb",
value: function decimalToRgb(decimal) {
var r = decimal >> 16 & 255;
var g = decimal >> 8 & 255;
var b = decimal & 255;
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
}]);
}(); //弹幕过滤
_defineProperty(YbDanmu, "DEFAULT_CONFIG", {
accuracy: 1,
//绘制精度 auto-自动使用屏幕DPI 任意整数-自定义精度 高精度会导致性能问题,谨慎使用
speed: 1,
//弹幕运行速度
playbackRate: 1,
//弹幕倍速
color: '#FFFFFF',
//弹幕默认颜色
fontSize: 18,
//弹幕默认大小
fontScale: 1,
//弹幕规格(多少倍大小)
fontFamily: 'Microsoft Yahei',
//弹幕默认字体
opacity: 1,
//弹幕透明度
top: 0,
//舞台顶部间距
bottom: 0,
//舞台底部间距
lineGap: 5,
//弹幕行间距
overlap: false,
//开启防重叠
timeDiffrence: 0,
//时间差(用于校准弹幕和视频进度的时间差,一般不需要)
disableScroll: false,
//关闭滚动弹幕
disableTop: false,
//关闭顶端弹幕
disableBottom: false,
//关闭底端弹幕
disableFilter: false,
//关闭弹幕过滤
filter: [] //过滤列表
});
var YbDanmuFilter = /*#__PURE__*/function () {
function YbDanmuFilter(list) {
_classCallCheck(this, YbDanmuFilter);
this.rules = list || [];
}
// 添加
return _createClass(YbDanmuFilter, [{
key: "add",
value: function add(rule) {
//判断是否存在同类型的相同规则
var index = this.rules.findIndex(function (r) {
return r.pattern == rule.pattern && r.type == rule.type;
});
if (index > -1) return false; //如果已经存在返回false表示插入失败
this.rules.push(rule);
return true; //添加成功返回true
}
// 删除
}, {
key: "remove",
value: function remove(index) {
this.rules.splice(index, 1);
}
// 过滤弹幕
}, {
key: "filter",
value: function filter(danmu) {
var _iterator = _createForOfIteratorHelper(this.rules),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var rule = _step.value;
if (rule.type === 'string') {
// 字符串匹配
if (danmu.includes(rule.pattern)) {
return true;
}
} else if (rule.type === 'regex') {
// 正则表达式匹配
try {
var regex = new RegExp(rule.pattern);
if (regex.test(danmu)) {
return true;
}
} catch (e) {
console.error('无效的正则表达式:', rule.pattern, e);
}
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return false;
}
// 获取所有规则
}, {
key: "getRules",
value: function getRules() {
return this.rules;
}
}]);
}(); //兼容new Function为了挂载到window对象上
if (typeof window != 'undefined') {
window.YbDanmu = YbDanmu;
}