123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368 |
- module.exports =
- /******/ (function(modules) { // webpackBootstrap
- /******/ // The module cache
- /******/ var installedModules = {};
- /******/
- /******/ // The require function
- /******/ function __webpack_require__(moduleId) {
- /******/
- /******/ // Check if module is in cache
- /******/ if(installedModules[moduleId]) {
- /******/ return installedModules[moduleId].exports;
- /******/ }
- /******/ // Create a new module (and put it into the cache)
- /******/ var module = installedModules[moduleId] = {
- /******/ i: moduleId,
- /******/ l: false,
- /******/ exports: {}
- /******/ };
- /******/
- /******/ // Execute the module function
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
- /******/
- /******/ // Flag the module as loaded
- /******/ module.l = true;
- /******/
- /******/ // Return the exports of the module
- /******/ return module.exports;
- /******/ }
- /******/
- /******/
- /******/ // expose the modules object (__webpack_modules__)
- /******/ __webpack_require__.m = modules;
- /******/
- /******/ // expose the module cache
- /******/ __webpack_require__.c = installedModules;
- /******/
- /******/ // define getter function for harmony exports
- /******/ __webpack_require__.d = function(exports, name, getter) {
- /******/ if(!__webpack_require__.o(exports, name)) {
- /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
- /******/ }
- /******/ };
- /******/
- /******/ // define __esModule on exports
- /******/ __webpack_require__.r = function(exports) {
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
- /******/ }
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
- /******/ };
- /******/
- /******/ // create a fake namespace object
- /******/ // mode & 1: value is a module id, require it
- /******/ // mode & 2: merge all properties of value into the ns
- /******/ // mode & 4: return value when already ns object
- /******/ // mode & 8|1: behave like require
- /******/ __webpack_require__.t = function(value, mode) {
- /******/ if(mode & 1) value = __webpack_require__(value);
- /******/ if(mode & 8) return value;
- /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
- /******/ var ns = Object.create(null);
- /******/ __webpack_require__.r(ns);
- /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
- /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
- /******/ return ns;
- /******/ };
- /******/
- /******/ // getDefaultExport function for compatibility with non-harmony modules
- /******/ __webpack_require__.n = function(module) {
- /******/ var getter = module && module.__esModule ?
- /******/ function getDefault() { return module['default']; } :
- /******/ function getModuleExports() { return module; };
- /******/ __webpack_require__.d(getter, 'a', getter);
- /******/ return getter;
- /******/ };
- /******/
- /******/ // Object.prototype.hasOwnProperty.call
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
- /******/
- /******/ // __webpack_public_path__
- /******/ __webpack_require__.p = "";
- /******/
- /******/
- /******/ // Load entry module and return exports
- /******/ return __webpack_require__(__webpack_require__.s = 1);
- /******/ })
- /************************************************************************/
- /******/ ([
- /* 0 */
- /***/ (function(module, exports, __webpack_require__) {
- "use strict";
- // 获取字节长度,中文算2个字节
- function getStrLen(str) {
- // eslint-disable-next-line no-control-regex
- return str.replace(/[^\x00-\xff]/g, 'aa').length;
- }
- // 截取指定字节长度的子串
- function substring(str, n) {
- if (!str) return '';
- var len = getStrLen(str);
- if (n >= len) return str;
- var l = 0;
- var result = '';
- for (var i = 0; i < str.length; i++) {
- var ch = str.charAt(i);
- // eslint-disable-next-line no-control-regex
- l = /[^\x00-\xff]/i.test(ch) ? l + 2 : l + 1;
- result += ch;
- if (l >= n) break;
- }
- return result;
- }
- function getRandom() {
- var max = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10;
- var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- return Math.floor(Math.random() * (max - min) + min);
- }
- function getFontSize(font) {
- var reg = /(\d+)(px)/i;
- var match = font.match(reg);
- return match && match[1] || 10;
- }
- function compareVersion(v1, v2) {
- v1 = v1.split('.');
- v2 = v2.split('.');
- var len = Math.max(v1.length, v2.length);
- while (v1.length < len) {
- v1.push('0');
- }
- while (v2.length < len) {
- v2.push('0');
- }
- for (var i = 0; i < len; i++) {
- var num1 = parseInt(v1[i], 10);
- var num2 = parseInt(v2[i], 10);
- if (num1 > num2) {
- return 1;
- } else if (num1 < num2) {
- return -1;
- }
- }
- return 0;
- }
- module.exports = {
- getStrLen: getStrLen,
- substring: substring,
- getRandom: getRandom,
- getFontSize: getFontSize,
- compareVersion: compareVersion
- };
- /***/ }),
- /* 1 */
- /***/ (function(module, exports, __webpack_require__) {
- "use strict";
- var _barrageDom = __webpack_require__(2);
- var _barrageDom2 = _interopRequireDefault(_barrageDom);
- var _barrageCanvas = __webpack_require__(3);
- var _barrageCanvas2 = _interopRequireDefault(_barrageCanvas);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- Component({
- options: {
- addGlobalClass: true
- },
- properties: {
- zIndex: {
- type: Number,
- value: 10
- },
- renderingMode: {
- type: String,
- value: 'canvas'
- }
- },
- methods: {
- getBarrageInstance: function getBarrageInstance() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- opt.comp = this;
- this.barrageInstance = this.data.renderingMode === 'dom' ? new _barrageDom2.default(opt) : new _barrageCanvas2.default(opt);
- return this.barrageInstance;
- },
- onAnimationend: function onAnimationend(e) {
- var _e$currentTarget$data = e.currentTarget.dataset,
- tunnelid = _e$currentTarget$data.tunnelid,
- bulletid = _e$currentTarget$data.bulletid;
- this.barrageInstance.animationend({
- tunnelId: tunnelid,
- bulletId: bulletid
- });
- },
- onTapBullet: function onTapBullet(e) {
- var _e$currentTarget$data2 = e.currentTarget.dataset,
- tunnelid = _e$currentTarget$data2.tunnelid,
- bulletid = _e$currentTarget$data2.bulletid;
- this.barrageInstance.tapBullet({
- tunnelId: tunnelid,
- bulletId: bulletid
- });
- }
- }
- });
- /***/ }),
- /* 2 */
- /***/ (function(module, exports, __webpack_require__) {
- "use strict";
- exports.__esModule = true;
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- var _require = __webpack_require__(0),
- substring = _require.substring,
- getRandom = _require.getRandom,
- getFontSize = _require.getFontSize;
- var Bullet = function () {
- function Bullet() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- _classCallCheck(this, Bullet);
- this.bulletId = opt.bulletId;
- this.addContent(opt);
- }
- /**
- * image 结构
- * {
- * head: {src, width, height},
- * tail: {src, width, height},
- * gap: 4 // 图片与文本间隔
- * }
- */
- Bullet.prototype.addContent = function addContent() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var defaultBulletOpt = {
- duration: 0, // 动画时长
- passtime: 0, // 弹幕穿越右边界耗时
- content: '', // 文本
- color: '#000000', // 默认黑色
- width: 0, // 弹幕宽度
- height: 0, // 弹幕高度
- image: {}, // 图片
- paused: false // 是否暂停
- };
- Object.assign(this, defaultBulletOpt, opt);
- };
- Bullet.prototype.removeContent = function removeContent() {
- this.addContent({});
- };
- return Bullet;
- }();
- // tunnel(轨道)
- var Tunnel = function () {
- function Tunnel() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- _classCallCheck(this, Tunnel);
- var defaultTunnelOpt = {
- tunnelId: 0,
- height: 0, // 轨道高度
- width: 0, // 轨道宽度
- safeGap: 4, // 相邻弹幕安全间隔
- maxNum: 10, // 缓冲队列长度
- bullets: [], // 弹幕
- last: -1, // 上一条发送的弹幕序号
- bulletStatus: [], // 0 空闲,1 占用中
- disabled: false, // 禁用中
- sending: false, // 弹幕正在发送
- timer: null // 定时器
- };
- Object.assign(this, defaultTunnelOpt, opt);
- this.bulletStatus = new Array(this.maxNum).fill(0);
- for (var i = 0; i < this.maxNum; i++) {
- this.bullets.push(new Bullet({
- bulletId: i
- }));
- }
- }
- Tunnel.prototype.disable = function disable() {
- this.disabled = true;
- this.last = -1;
- this.sending = false;
- this.bulletStatus = new Array(this.maxNum).fill(1);
- this.bullets.forEach(function (bullet) {
- return bullet.removeContent();
- });
- };
- Tunnel.prototype.enable = function enable() {
- if (this.disabled) {
- this.bulletStatus = new Array(this.maxNum).fill(0);
- }
- this.disabled = false;
- };
- Tunnel.prototype.clear = function clear() {
- this.last = -1;
- this.sending = false;
- this.bulletStatus = new Array(this.maxNum).fill(0);
- this.bullets.forEach(function (bullet) {
- return bullet.removeContent();
- });
- if (this.timer) {
- clearTimeout(this.timer);
- }
- };
- Tunnel.prototype.getIdleBulletIdx = function getIdleBulletIdx() {
- var idle = this.bulletStatus.indexOf(0, this.last + 1);
- if (idle === -1) {
- idle = this.bulletStatus.indexOf(0);
- }
- return idle;
- };
- Tunnel.prototype.getIdleBulletNum = function getIdleBulletNum() {
- var count = 0;
- this.bulletStatus.forEach(function (status) {
- if (status === 0) count++;
- });
- return count;
- };
- Tunnel.prototype.addBullet = function addBullet(opt) {
- if (this.disabled) return;
- var idx = this.getIdleBulletIdx();
- if (idx >= 0) {
- this.bulletStatus[idx] = 1;
- this.bullets[idx].addContent(opt);
- }
- };
- Tunnel.prototype.removeBullet = function removeBullet(bulletId) {
- if (this.disabled) return;
- this.bulletStatus[bulletId] = 0;
- var bullet = this.bullets[bulletId];
- bullet.removeContent();
- };
- return Tunnel;
- }();
- // Barrage(控制中心)
- var Barrage = function () {
- function Barrage() {
- var _this = this;
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- _classCallCheck(this, Barrage);
- var defaultBarrageOpt = {
- duration: 10, // 弹幕动画时长
- lineHeight: 1.2, // 弹幕行高
- padding: [0, 0, 0, 0], // 弹幕区四周留白
- alpha: 1, // 全局透明度
- font: '10px sans-serif', // 全局字体
- mode: 'separate', // 弹幕重叠 overlap 不重叠 separate
- range: [0, 1], // 弹幕显示的垂直范围,支持两个值。[0,1]表示弹幕整个随机分布,
- tunnelShow: false, // 显示轨道线
- tunnelMaxNum: 30, // 隧道最大缓冲长度
- maxLength: 30, // 弹幕最大字节长度,汉字算双字节
- safeGap: 4, // 发送时的安全间隔
- enableTap: false, // 点击弹幕停止动画高亮显示
- tunnelHeight: 0,
- tunnelNum: 0,
- tunnels: [],
- idleTunnels: null,
- enableTunnels: null,
- distance: 2000,
- comp: null // 组件实例
- };
- Object.assign(this, defaultBarrageOpt, opt);
- this._ready = false;
- this._deferred = [];
- var query = this.comp.createSelectorQuery();
- query.select('.barrage-area').boundingClientRect(function (res) {
- _this.init(res);
- _this.ready();
- }).exec();
- }
- Barrage.prototype.ready = function ready() {
- var _this2 = this;
- this._ready = true;
- this._deferred.forEach(function (item) {
- // eslint-disable-next-line prefer-spread
- _this2[item.callback].apply(_this2, item.args);
- });
- this._deferred = [];
- };
- Barrage.prototype._delay = function _delay(method, args) {
- this._deferred.push({
- callback: method,
- args: args
- });
- };
- Barrage.prototype.init = function init(opt) {
- this.width = opt.width;
- this.height = opt.height;
- this.fontSize = getFontSize(this.font);
- this.idleTunnels = new Set();
- this.enableTunnels = new Set();
- this.tunnels = [];
- this.availableHeight = this.height - this.padding[0] - this.padding[2];
- this.tunnelHeight = this.fontSize * this.lineHeight;
- this.tunnelNum = Math.floor(this.availableHeight / this.tunnelHeight);
- for (var i = 0; i < this.tunnelNum; i++) {
- this.idleTunnels.add(i); // 空闲的隧道id集合
- this.enableTunnels.add(i); // 可用的隧道id集合
- this.tunnels.push(new Tunnel({ // 隧道集合
- width: this.width,
- height: this.tunnelHeight,
- safeGap: this.safeGap,
- maxNum: this.tunnelMaxNum,
- tunnelId: i
- }));
- }
- this.comp.setData({
- fontSize: this.fontSize,
- tunnelShow: this.tunnelShow,
- tunnels: this.tunnels,
- font: this.font,
- alpha: this.alpha,
- padding: this.padding.map(function (item) {
- return item + 'px';
- }).join(' ')
- });
- // 筛选符合范围的隧道
- this.setRange();
- };
- // 设置显示范围 range: [0,1]
- Barrage.prototype.setRange = function setRange(range) {
- var _this3 = this;
- if (!this._ready) {
- this._delay('setRange', range);
- return;
- }
- range = range || this.range;
- var top = range[0] * this.tunnelNum;
- var bottom = range[1] * this.tunnelNum;
- // 释放符合要求的隧道
- // 找到目前空闲的隧道
- var idleTunnels = new Set();
- var enableTunnels = new Set();
- this.tunnels.forEach(function (tunnel, tunnelId) {
- if (tunnelId >= top && tunnelId < bottom) {
- var disabled = tunnel.disabled;
- tunnel.enable();
- enableTunnels.add(tunnelId);
- if (disabled || _this3.idleTunnels.has(tunnelId)) {
- idleTunnels.add(tunnelId);
- }
- } else {
- tunnel.disable();
- }
- });
- this.idleTunnels = idleTunnels;
- this.enableTunnels = enableTunnels;
- this.range = range;
- this.comp.setData({ tunnels: this.tunnels });
- };
- Barrage.prototype.setFont = function setFont(font) {
- if (!this._ready) {
- this._delay('setFont', font);
- return;
- }
- if (typeof font !== 'string') return;
- this.font = font;
- this.comp.setData({ font: font });
- };
- Barrage.prototype.setAlpha = function setAlpha(alpha) {
- if (!this._ready) {
- this._delay('setAlpha', alpha);
- return;
- }
- if (typeof alpha !== 'number') return;
- this.alpha = alpha;
- this.comp.setData({ alpha: alpha });
- };
- Barrage.prototype.setDuration = function setDuration(duration) {
- if (!this._ready) {
- this._delay('setDuration', duration);
- return;
- }
- if (typeof duration !== 'number') return;
- this.duration = duration;
- this.clear();
- };
- // 开启弹幕
- Barrage.prototype.open = function open() {
- if (!this._ready) {
- this._delay('open');
- return;
- }
- this._isActive = true;
- };
- // 关闭弹幕,清除所有数据
- Barrage.prototype.close = function close() {
- if (!this._ready) {
- this._delay('close');
- return;
- }
- this._isActive = false;
- this.clear();
- };
- Barrage.prototype.clear = function clear() {
- this.tunnels.forEach(function (tunnel) {
- return tunnel.clear();
- });
- this.idleTunnels = new Set(this.enableTunnels);
- this.comp.setData({ tunnels: this.tunnels });
- };
- // 添加一批弹幕,轨道满时会被丢弃
- Barrage.prototype.addData = function addData() {
- var _this4 = this;
- var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
- if (!this._ready) {
- this._delay('addData', data);
- return;
- }
- if (!this._isActive) return;
- data.forEach(function (item) {
- item.content = substring(item.content, _this4.maxLength);
- _this4.addBullet2Tunnel(item);
- });
- this.comp.setData({
- tunnels: this.tunnels
- }, function () {
- _this4.updateBullets();
- });
- };
- // 发送一条弹幕
- Barrage.prototype.send = function send() {
- var _this5 = this;
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- if (!this._ready) {
- this._delay('send', opt);
- return;
- }
- var tunnel = this.getEnableTunnel();
- if (tunnel === null) return;
- var timer = setInterval(function () {
- var tunnel = _this5.getIdleTunnel();
- if (tunnel) {
- _this5.addData([opt]);
- clearInterval(timer);
- }
- }, 16);
- };
- // 添加至轨道
- Barrage.prototype.addBullet2Tunnel = function addBullet2Tunnel() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var tunnel = this.getIdleTunnel();
- if (tunnel === null) return;
- var tunnelId = tunnel.tunnelId;
- tunnel.addBullet(opt);
- if (tunnel.getIdleBulletNum() === 0) this.removeIdleTunnel(tunnelId);
- };
- Barrage.prototype.updateBullets = function updateBullets() {
- var _this6 = this;
- var self = this;
- var query = this.comp.createSelectorQuery();
- query.selectAll('.bullet-item').boundingClientRect(function (res) {
- if (!_this6._isActive) return;
- for (var i = 0; i < res.length; i++) {
- var _res$i$dataset = res[i].dataset,
- tunnelid = _res$i$dataset.tunnelid,
- bulletid = _res$i$dataset.bulletid;
- var tunnel = self.tunnels[tunnelid];
- var bullet = tunnel.bullets[bulletid];
- bullet.width = res[i].width;
- bullet.height = res[i].height;
- }
- self.animate();
- }).exec();
- };
- Barrage.prototype.animate = function animate() {
- var _this7 = this;
- this.tunnels.forEach(function (tunnel) {
- _this7.tunnelAnimate(tunnel);
- });
- };
- Barrage.prototype.tunnelAnimate = function tunnelAnimate(tunnel) {
- var _this8 = this;
- if (tunnel.disabled || tunnel.sending || !this._isActive) return;
- var next = (tunnel.last + 1) % tunnel.maxNum;
- var bullet = tunnel.bullets[next];
- if (!bullet) return;
- if (bullet.content || bullet.image.head || bullet.image.tail) {
- var _comp$setData;
- tunnel.sending = true;
- tunnel.last = next;
- var duration = this.duration;
- if (this.mode === 'overlap') {
- duration = this.distance * this.duration / (this.distance + bullet.width);
- }
- var passDistance = bullet.width + tunnel.safeGap;
- bullet.duration = duration;
- // 等上一条通过右边界
- bullet.passtime = Math.ceil(passDistance * bullet.duration * 1000 / this.distance);
- this.comp.setData((_comp$setData = {}, _comp$setData['tunnels[' + tunnel.tunnelId + '].bullets[' + bullet.bulletId + ']'] = bullet, _comp$setData), function () {
- tunnel.timer = setTimeout(function () {
- tunnel.sending = false;
- _this8.tunnelAnimate(tunnel);
- }, bullet.passtime);
- });
- }
- };
- Barrage.prototype.showTunnel = function showTunnel() {
- this.comp.setData({
- tunnelShow: true
- });
- };
- Barrage.prototype.hideTunnel = function hideTunnel() {
- this.comp.setData({
- tunnelShow: false
- });
- };
- Barrage.prototype.removeIdleTunnel = function removeIdleTunnel(tunnelId) {
- this.idleTunnels.delete(tunnelId);
- };
- Barrage.prototype.addIdleTunnel = function addIdleTunnel(tunnelId) {
- this.idleTunnels.add(tunnelId);
- };
- // 从可用的隧道中随机挑选一个
- Barrage.prototype.getEnableTunnel = function getEnableTunnel() {
- if (this.enableTunnels.size === 0) return null;
- var enableTunnels = Array.from(this.enableTunnels);
- var index = getRandom(enableTunnels.length);
- return this.tunnels[enableTunnels[index]];
- };
- // 从还有余量的隧道中随机挑选一个
- Barrage.prototype.getIdleTunnel = function getIdleTunnel() {
- if (this.idleTunnels.size === 0) return null;
- var idleTunnels = Array.from(this.idleTunnels);
- var index = getRandom(idleTunnels.length);
- return this.tunnels[idleTunnels[index]];
- };
- Barrage.prototype.animationend = function animationend(opt) {
- var _comp$setData2;
- var tunnelId = opt.tunnelId,
- bulletId = opt.bulletId;
- var tunnel = this.tunnels[tunnelId];
- var bullet = tunnel.bullets[bulletId];
- if (!tunnel || !bullet) return;
- tunnel.removeBullet(bulletId);
- this.addIdleTunnel(tunnelId);
- this.comp.setData((_comp$setData2 = {}, _comp$setData2['tunnels[' + tunnelId + '].bullets[' + bulletId + ']'] = bullet, _comp$setData2));
- };
- Barrage.prototype.tapBullet = function tapBullet(opt) {
- var _comp$setData3;
- if (!this.enableTap) return;
- var tunnelId = opt.tunnelId,
- bulletId = opt.bulletId;
- var tunnel = this.tunnels[tunnelId];
- var bullet = tunnel.bullets[bulletId];
- bullet.paused = !bullet.paused;
- this.comp.setData((_comp$setData3 = {}, _comp$setData3['tunnels[' + tunnelId + '].bullets[' + bulletId + ']'] = bullet, _comp$setData3));
- };
- return Barrage;
- }();
- exports.default = Barrage;
- /***/ }),
- /* 3 */
- /***/ (function(module, exports, __webpack_require__) {
- "use strict";
- exports.__esModule = true;
- var _utils = __webpack_require__(0);
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- var Bullet = function () {
- function Bullet(barrage) {
- var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- _classCallCheck(this, Bullet);
- var defaultBulletOpt = {
- color: '#000000', // 默认黑色
- font: '10px sans-serif',
- fontSize: 10, // 全局字体大小
- content: '',
- textWidth: 0,
- speed: 0, // 根据屏幕停留时长计算
- x: 0,
- y: 0,
- tunnelId: 0,
- // image: {
- // head: {src, width, height}, // 弹幕头部添加图片
- // tail: {src, width, height}, // 弹幕尾部添加图片
- // gap: 4 // 图片与文本间隔
- // }
- image: {},
- imageHead: null, // Image 对象
- imageTail: null
- // status: 0 //0:待播放 1: 未完全进入屏幕 2: 完全进入屏幕 3: 完全退出屏幕
- };
- Object.assign(this, defaultBulletOpt, opt);
- this.barrage = barrage;
- this.ctx = barrage.ctx;
- this.canvas = barrage.canvas;
- }
- Bullet.prototype.move = function move() {
- var _this = this;
- if (this.image.head && !this.imageHead) {
- var Image = this.canvas.createImage();
- Image.src = this.image.head.src;
- Image.onload = function () {
- _this.imageHead = Image;
- };
- Image.onerror = function () {
- // eslint-disable-next-line no-console
- console.log('Fail to load image: ' + _this.image.head.src);
- };
- }
- if (this.image.tail && !this.imageTail) {
- var _Image = this.canvas.createImage();
- _Image.src = this.image.tail.src;
- _Image.onload = function () {
- _this.imageTail = _Image;
- };
- _Image.onerror = function () {
- // eslint-disable-next-line no-console
- console.log('Fail to load image: ' + _this.image.tail.src);
- };
- }
- if (this.imageHead) {
- var _image$head = this.image.head,
- _image$head$width = _image$head.width,
- width = _image$head$width === undefined ? this.fontSize : _image$head$width,
- _image$head$height = _image$head.height,
- height = _image$head$height === undefined ? this.fontSize : _image$head$height,
- _image$head$gap = _image$head.gap,
- gap = _image$head$gap === undefined ? 4 : _image$head$gap;
- var x = this.x - gap - width;
- var y = this.y - 0.5 * height;
- this.ctx.drawImage(this.imageHead, x, y, width, height);
- }
- if (this.imageTail) {
- var _image$tail = this.image.tail,
- _image$tail$width = _image$tail.width,
- _width = _image$tail$width === undefined ? this.fontSize : _image$tail$width,
- _image$tail$height = _image$tail.height,
- _height = _image$tail$height === undefined ? this.fontSize : _image$tail$height,
- _image$tail$gap = _image$tail.gap,
- _gap = _image$tail$gap === undefined ? 4 : _image$tail$gap;
- var _x2 = this.x + this.textWidth + _gap;
- var _y = this.y - 0.5 * _height;
- this.ctx.drawImage(this.imageTail, _x2, _y, _width, _height);
- }
- this.x = this.x - this.speed;
- this.ctx.fillStyle = this.color;
- this.ctx.fillText(this.content, this.x, this.y);
- };
- return Bullet;
- }();
- // tunnel(轨道)
- var Tunnel = function () {
- function Tunnel(barrage) {
- var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- _classCallCheck(this, Tunnel);
- var defaultTunnelOpt = {
- activeQueue: [], // 正在屏幕中列表
- nextQueue: [], // 待播放列表
- maxNum: 30,
- freeNum: 30, // 剩余可添加量
- height: 0,
- width: 0,
- disabled: false,
- tunnelId: 0,
- safeArea: 4,
- sending: false // 弹幕正在发送
- };
- Object.assign(this, defaultTunnelOpt, opt);
- this.freeNum = this.maxNum;
- this.barrage = barrage; // 控制中心
- this.ctx = barrage.ctx;
- }
- Tunnel.prototype.disable = function disable() {
- this.disabled = true;
- };
- Tunnel.prototype.enable = function enable() {
- this.disabled = false;
- };
- Tunnel.prototype.clear = function clear() {
- this.activeQueue = [];
- this.nextQueue = [];
- this.sending = false;
- this.freeNum = this.maxNum;
- this.barrage.addIdleTunnel(this.tunnelId);
- };
- Tunnel.prototype.addBullet = function addBullet(bullet) {
- if (this.disabled) return;
- if (this.freeNum === 0) return;
- this.nextQueue.push(bullet);
- this.freeNum--;
- if (this.freeNum === 0) {
- this.barrage.removeIdleTunnel(this.tunnelId);
- }
- };
- Tunnel.prototype.animate = function animate() {
- if (this.disabled) return;
- // 无正在发送弹幕,添加一条
- var nextQueue = this.nextQueue;
- var activeQueue = this.activeQueue;
- if (!this.sending && nextQueue.length > 0) {
- var bullet = nextQueue.shift();
- activeQueue.push(bullet);
- this.freeNum++;
- this.sending = true;
- this.barrage.addIdleTunnel(this.tunnelId);
- }
- if (activeQueue.length > 0) {
- activeQueue.forEach(function (bullet) {
- return bullet.move();
- });
- var head = activeQueue[0];
- var tail = activeQueue[activeQueue.length - 1];
- // 队首移出屏幕
- if (head.x + head.textWidth < 0) {
- activeQueue.shift();
- }
- // 队尾离开超过安全区
- if (tail.x + tail.textWidth + this.safeArea < this.width) {
- this.sending = false;
- }
- }
- };
- return Tunnel;
- }();
- var Barrage = function () {
- function Barrage() {
- var _this2 = this;
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- _classCallCheck(this, Barrage);
- var defaultBarrageOpt = {
- font: '10px sans-serif',
- duration: 15, // 弹幕屏幕停留时长
- lineHeight: 1.2,
- padding: [0, 0, 0, 0],
- tunnelHeight: 0,
- tunnelNum: 0,
- tunnelMaxNum: 30, // 隧道最大缓冲长度
- maxLength: 30, // 最大字节长度,汉字算双字节
- safeArea: 4, // 发送时的安全间隔
- tunnels: [],
- idleTunnels: [],
- enableTunnels: [],
- alpha: 1, // 全局透明度
- mode: 'separate', // 弹幕重叠 overlap 不重叠 separate
- range: [0, 1], // 弹幕显示的垂直范围,支持两个值。[0,1]表示弹幕整个随机分布,
- fps: 60, // 刷新率
- tunnelShow: false, // 显示轨道线
- comp: null // 组件实例
- };
- Object.assign(this, defaultBarrageOpt, opt);
- var systemInfo = wx.getSystemInfoSync();
- this.ratio = systemInfo.pixelRatio;
- this.selector = '#weui-canvas';
- this._ready = false;
- this._deferred = [];
- var query = this.comp.createSelectorQuery();
- query.select(this.selector).boundingClientRect();
- query.select(this.selector).node();
- query.exec(function (res) {
- _this2.canvas = res[1].node;
- _this2.init(res[0]);
- _this2.ready();
- });
- }
- Barrage.prototype.ready = function ready() {
- var _this3 = this;
- this._ready = true;
- this._deferred.forEach(function (item) {
- // eslint-disable-next-line prefer-spread
- _this3[item.callback].apply(_this3, item.args);
- });
- this._deferred = [];
- };
- Barrage.prototype._delay = function _delay(method, args) {
- this._deferred.push({
- callback: method,
- args: args
- });
- };
- Barrage.prototype.init = function init() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- this.width = opt.width;
- this.height = opt.height;
- this.fontSize = (0, _utils.getFontSize)(this.font);
- this.innerDuration = this.transfromDuration2Canvas(this.duration);
- var ratio = this.ratio; // 设备像素比
- this.canvas.width = this.width * ratio;
- this.canvas.height = this.height * ratio;
- this.ctx = this.canvas.getContext('2d');
- this.ctx.scale(ratio, ratio);
- this.ctx.textBaseline = 'middle';
- this.ctx.globalAlpha = this.alpha;
- this.ctx.font = this.font;
- this.idleTunnels = [];
- this.enableTunnels = [];
- this.tunnels = [];
- this.availableHeight = this.height - this.padding[0] - this.padding[2];
- this.tunnelHeight = this.fontSize * this.lineHeight;
- this.tunnelNum = Math.floor(this.availableHeight / this.tunnelHeight);
- for (var i = 0; i < this.tunnelNum; i++) {
- this.idleTunnels.push(i); // 空闲的隧道id集合
- this.enableTunnels.push(i); // 可用的隧道id集合
- this.tunnels.push(new Tunnel(this, { // 隧道集合
- width: this.width,
- height: this.tunnelHeight,
- safeArea: this.safeArea,
- maxNum: this.tunnelMaxNum,
- tunnelId: i
- }));
- }
- // 筛选符合范围的隧道
- this.setRange();
- this._isActive = false;
- };
- Barrage.prototype.transfromDuration2Canvas = function transfromDuration2Canvas(duration) {
- // 2000 是 dom 中移动的距离
- return duration * this.width / 2000;
- };
- // 设置显示范围 range: [0,1]
- Barrage.prototype.setRange = function setRange(range) {
- var _this4 = this;
- if (!this._ready) {
- this._delay('setRange', range);
- return;
- }
- range = range || this.range;
- var top = range[0] * this.tunnelNum;
- var bottom = range[1] * this.tunnelNum;
- // 释放符合要求的隧道
- // 找到目前空闲的隧道
- var idleTunnels = [];
- var enableTunnels = [];
- this.tunnels.forEach(function (tunnel, tunnelId) {
- if (tunnelId >= top && tunnelId < bottom) {
- tunnel.enable();
- enableTunnels.push(tunnelId);
- if (_this4.idleTunnels.indexOf(tunnelId) >= 0) {
- idleTunnels.push(tunnelId);
- }
- } else {
- tunnel.disable();
- }
- });
- this.idleTunnels = idleTunnels;
- this.enableTunnels = enableTunnels;
- this.range = range;
- };
- Barrage.prototype.setFont = function setFont(font) {
- if (!this._ready) {
- this._delay('setFont', font);
- return;
- }
- this.font = font;
- this.fontSize = (0, _utils.getFontSize)(this.font);
- this.ctx.font = font;
- };
- Barrage.prototype.setAlpha = function setAlpha(alpha) {
- if (!this._ready) {
- this._delay('setAlpha', alpha);
- return;
- }
- this.alpha = alpha;
- this.ctx.globalAlpha = alpha;
- };
- Barrage.prototype.setDuration = function setDuration(duration) {
- if (!this._ready) {
- this._delay('setDuration', duration);
- return;
- }
- this.clear();
- this.duration = duration;
- this.innerDuration = this.transfromDuration2Canvas(duration);
- };
- // 开启弹幕
- Barrage.prototype.open = function open() {
- if (!this._ready) {
- this._delay('open');
- return;
- }
- if (this._isActive) return;
- this._isActive = true;
- this.play();
- };
- // 关闭弹幕,清除所有数据
- Barrage.prototype.close = function close() {
- if (!this._ready) {
- this._delay('close');
- return;
- }
- if (!this._isActive) return;
- this._isActive = false;
- this.pause();
- this.clear();
- };
- // 开启弹幕滚动
- Barrage.prototype.play = function play() {
- var _this5 = this;
- this._rAFId = this.canvas.requestAnimationFrame(function () {
- _this5.animate();
- _this5.play();
- });
- };
- // 停止弹幕滚动
- Barrage.prototype.pause = function pause() {
- if (typeof this._rAFId === 'number') {
- this.canvas.cancelAnimationFrame(this._rAFId);
- }
- };
- // 清空屏幕和缓冲的数据
- Barrage.prototype.clear = function clear() {
- this.ctx.clearRect(0, 0, this.width, this.height);
- this.tunnels.forEach(function (tunnel) {
- return tunnel.clear();
- });
- };
- // 添加一批弹幕,轨道满时会被丢弃
- Barrage.prototype.addData = function addData() {
- var _this6 = this;
- var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
- if (!this._ready) {
- this._delay('addData', data);
- return;
- }
- if (!this._isActive) return;
- data.forEach(function (item) {
- return _this6.addBullet2Tunnel(item);
- });
- };
- // 发送一条弹幕
- // 为保证发送成功,选取一条可用隧道,替换待发送队列队头元素
- Barrage.prototype.send = function send() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- if (!this._ready) {
- this._delay('send', opt);
- return;
- }
- var tunnel = this.getEnableTunnel();
- if (tunnel === null) return;
- opt.tunnelId = tunnel.tunnelId;
- var bullet = this.registerBullet(opt);
- tunnel.nextQueue[0] = bullet;
- };
- // 添加至轨道 {content, color}
- Barrage.prototype.addBullet2Tunnel = function addBullet2Tunnel() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var tunnel = this.getIdleTunnel();
- if (tunnel === null) return;
- opt.tunnelId = tunnel.tunnelId;
- var bullet = this.registerBullet(opt);
- tunnel.addBullet(bullet);
- };
- Barrage.prototype.registerBullet = function registerBullet() {
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- opt.tunnelId = opt.tunnelId || 0;
- opt.content = (0, _utils.substring)(opt.content, this.maxLength);
- var textWidth = this.getTextWidth(opt.content);
- var distance = this.mode === 'overlap' ? this.width + textWidth : this.width;
- opt.textWidth = textWidth;
- opt.speed = distance / (this.innerDuration * this.fps);
- opt.fontSize = this.fontSize;
- opt.x = this.width;
- opt.y = this.tunnelHeight * (opt.tunnelId + 0.5) + this.padding[0];
- return new Bullet(this, opt);
- };
- // 每帧执行的操作
- Barrage.prototype.animate = function animate() {
- // 清空画面后重绘
- this.ctx.clearRect(0, 0, this.width, this.height);
- if (this.tunnelShow) {
- this.drawTunnel();
- }
- this.tunnels.forEach(function (tunnel) {
- return tunnel.animate();
- });
- };
- Barrage.prototype.showTunnel = function showTunnel() {
- this.tunnelShow = true;
- };
- Barrage.prototype.hideTunnel = function hideTunnel() {
- this.tunnelShow = false;
- };
- Barrage.prototype.removeIdleTunnel = function removeIdleTunnel(tunnelId) {
- var idx = this.idleTunnels.indexOf(tunnelId);
- if (idx >= 0) this.idleTunnels.splice(idx, 1);
- };
- Barrage.prototype.addIdleTunnel = function addIdleTunnel(tunnelId) {
- var idx = this.idleTunnels.indexOf(tunnelId);
- if (idx < 0) this.idleTunnels.push(tunnelId);
- };
- // 从可用的隧道中随机挑选一个
- Barrage.prototype.getEnableTunnel = function getEnableTunnel() {
- if (this.enableTunnels.length === 0) return null;
- var index = (0, _utils.getRandom)(this.enableTunnels.length);
- return this.tunnels[this.enableTunnels[index]];
- };
- // 从还有余量的隧道中随机挑选一个
- Barrage.prototype.getIdleTunnel = function getIdleTunnel() {
- if (this.idleTunnels.length === 0) return null;
- var index = (0, _utils.getRandom)(this.idleTunnels.length);
- return this.tunnels[this.idleTunnels[index]];
- };
- Barrage.prototype.getTextWidth = function getTextWidth(content) {
- this.ctx.font = this.font;
- return Math.ceil(this.ctx.measureText(content).width);
- };
- Barrage.prototype.drawTunnel = function drawTunnel() {
- var ctx = this.ctx;
- var tunnelColor = '#CCB24D';
- for (var i = 0; i <= this.tunnelNum; i++) {
- var y = this.padding[0] + i * this.tunnelHeight;
- ctx.beginPath();
- ctx.strokeStyle = tunnelColor;
- ctx.setLineDash([5, 10]);
- ctx.moveTo(0, y);
- ctx.lineTo(this.width, y);
- ctx.stroke();
- if (i < this.tunnelNum) {
- ctx.fillStyle = tunnelColor;
- ctx.fillText('\u5F39\u9053' + (i + 1), 10, this.tunnelHeight / 2 + y);
- }
- }
- };
- return Barrage;
- }();
- exports.default = Barrage;
- /***/ })
- /******/ ]);
|