├── .gitignore
├── babel.config.json
├── types
└── index.d.ts
├── src
├── index.js
├── extend.js
├── barrage.js
├── index.vue
└── track.js
├── webpack.config.js
├── package.json
├── .github
└── workflows
│ └── static.yml
├── README.md
├── example
├── index.html
└── index.js
└── lib
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/babel.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"]
3 | }
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | export default function install(vue: typeof Vue): void
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Barrage from "../src/index.vue";
2 | export let vue
3 |
4 | export default function (Vue) {
5 | vue = Vue
6 | Vue.component(Barrage.name, Barrage)
7 | }
--------------------------------------------------------------------------------
/src/extend.js:
--------------------------------------------------------------------------------
1 | import { vue } from './index'
2 |
3 | export const createVueNode = (attributeData, slots) => vue.extend({
4 | render(h) {
5 | return h('div', attributeData, slots)
6 | }
7 | })
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { VueLoaderPlugin } = require('vue-loader')
2 | const path = require('path')
3 |
4 | module.exports = {
5 | entry: './src/index.js',
6 | // experiments: {
7 | // outputModule: true,
8 | // },
9 | output: {
10 | path: path.resolve('./lib'),
11 | filename: 'index.js',
12 | library: {
13 | name: 'Barrage',
14 | type: 'umd',
15 | export: 'default'
16 | // type: 'module'
17 | }
18 | },
19 | externals: {
20 | 'vue': 'Vue'
21 | },
22 | module: {
23 | rules: [
24 | {
25 | test: /\.vue/,
26 | use: 'vue-loader'
27 | },
28 | {
29 | test: /\.js$/,
30 | use: 'babel-loader'
31 | },
32 | {
33 | test: /\.css$/,
34 | use: ['vue-style-loader', 'css-loader']
35 | },
36 | ]
37 | },
38 | plugins: [
39 | new VueLoaderPlugin()
40 | ]
41 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-custom-barrage",
3 | "version": "0.0.6",
4 | "description": "基于 vue 的自定义弹幕组件",
5 | "author": "李少博",
6 | "homepage": "https://github.com/lishaobos/vue-custom-barrage#readme",
7 | "license": "ISC",
8 | "main": "lib/index.js",
9 | "directories": {
10 | "lib": "lib",
11 | "test": "__tests__"
12 | },
13 | "typings": "types/index.d.ts",
14 | "repository": {
15 | "type": "git",
16 | "url": "git+https://github.com/lishaobos/vue-custom-barrage.git"
17 | },
18 | "scripts": {
19 | "start": "webpack --mode development --watch",
20 | "build": "webpack --mode production"
21 | },
22 | "bugs": {
23 | "url": "https://github.com/lishaobos/vue-custom-barrage/issues"
24 | },
25 | "devDependencies": {
26 | "@babel/cli": "^7.15.4",
27 | "@babel/core": "^7.15.5",
28 | "@babel/preset-env": "^7.15.6",
29 | "babel-loader": "^8.2.2",
30 | "css-loader": "^6.2.0",
31 | "vue-loader": "^15.9.8",
32 | "vue-style-loader": "^4.1.3",
33 | "vue-template-compiler": "^2.6.14",
34 | "webpack": "^5.52.0",
35 | "webpack-cli": "^4.8.0"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/.github/workflows/static.yml:
--------------------------------------------------------------------------------
1 | # Simple workflow for deploying static content to GitHub Pages
2 | name: Deploy static content to Pages
3 |
4 | on:
5 | # Runs on pushes targeting the default branch
6 | push:
7 | branches: ["master"]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13 | permissions:
14 | contents: read
15 | pages: write
16 | id-token: write
17 |
18 | # Allow one concurrent deployment
19 | concurrency:
20 | group: "pages"
21 | cancel-in-progress: true
22 |
23 | jobs:
24 | # Single deploy job since we're just deploying
25 | deploy:
26 | environment:
27 | name: github-pages
28 | url: ${{ steps.deployment.outputs.page_url }}
29 | runs-on: ubuntu-latest
30 | steps:
31 | - name: Checkout
32 | uses: actions/checkout@v3
33 | - name: Setup Pages
34 | uses: actions/configure-pages@v2
35 | - name: Upload artifact
36 | uses: actions/upload-pages-artifact@v1
37 | with:
38 | path: 'example'
39 | - name: Deploy to GitHub Pages
40 | id: deployment
41 | uses: actions/deploy-pages@v1
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # `vue-custom-barrage`
2 |
3 | 支持用户使用插槽自定义弹幕,使用简单, 无须担心 XSS
4 |
5 | ## [DEMO](https://lishaobos.github.io/vue-custom-barrage/)
6 |
7 |
8 | ## Install
9 |
10 | ```
11 | npm i vue-custom-barrage
12 | ```
13 |
14 | ## Use
15 |
16 | ```
17 | import Vue from 'vue'
18 | import Barrage from 'vue-custom-barrage';
19 |
20 | Vue.use(Barrage)
21 | ```
22 |
23 |
24 | ## Example
25 |
26 | ```
27 |
28 |
29 |
30 | export default {
31 | data() {
32 | return {
33 | barrageData: ['text1', 'text2', 'text3']
34 | }
35 | }
36 | }
37 | ```
38 |
39 | ```
40 |
41 |
42 | 自定义弹幕 {{ data.text }}
43 |
44 |
45 |
46 | export default {
47 | data() {
48 | return {
49 | barrageData: [
50 | { text: 'text1' },
51 | { text: 'text2' },
52 | { text: 'text3' },
53 | ]
54 | }
55 | }
56 | }
57 | ```
58 |
59 | ## Options
60 |
61 | 参数 | 描述 | 类型 | 可选值 | 默认值
62 | --|:--:|--:|--:|--:
63 | pause | 是否全部暂停 | boolean | - | false
64 | touchPause | 是否触摸弹幕暂停 | boolean | - | false
65 | barrageClass | 弹幕类名 | string | - | -
66 | barrageStyle | 弹幕样式 | object | - | -
67 | showArea | 弹幕展示区域 | string | top / middle / bottom / all | all
68 | trackHeight | 弹幕轨道高度 | number | - | 20
69 | speed | 弹幕速度(单位:秒) | number | - | 10
70 | defer | 同一轨道弹幕完全出现至下条弹幕首次出现的间隔(单位:秒) | number | - | 0.5
71 | data | 弹幕数据 | array | - | []
--------------------------------------------------------------------------------
/src/barrage.js:
--------------------------------------------------------------------------------
1 | import Track from './track'
2 | export default class Barrage {
3 | constructor(instance) {
4 | this.instance = instance
5 | this.playState = 'running'
6 | this.tracks = []
7 | this.queue = []
8 | this.createTracks()
9 | }
10 |
11 | changePlayState(state) {
12 | this.playState = state
13 | this.instance.$el.style.setProperty('--playState', state)
14 | }
15 |
16 | pause() {
17 | this.changePlayState('paused')
18 |
19 | for (const item of this.tracks) {
20 | item.pause()
21 | }
22 | }
23 |
24 | start() {
25 | this.changePlayState('running')
26 |
27 | for (const item of this.tracks) {
28 | item.start()
29 | }
30 | }
31 |
32 | createTracks() {
33 | this.tracks.length = 0
34 | const height = this.instance.$el.offsetHeight
35 | const trackHeight = this.instance.trackHeight
36 | const stackNum = height / trackHeight
37 |
38 | // for (let i = 0; i < 1; i++) {
39 | for (let i = 0; i < stackNum; i++) {
40 | const track = new Track(i * trackHeight, this.instance, this.queue)
41 | this.tracks.push(track)
42 | }
43 | }
44 |
45 | setBullet(data) {
46 | Array.isArray(data) ? this.queue.push(...data) : this.queue.push(data)
47 |
48 | for (const track of this.tracks) {
49 | !track.isHidden && track.biubiu()
50 | }
51 | }
52 |
53 | // all top middle bottom
54 | showTracks(type) {
55 | if (type === 'all') {
56 | for (const track of this.tracks) {
57 | track.show()
58 | }
59 | return
60 | }
61 |
62 | const dis = Math.round(this.tracks.length / 3)
63 | const typeMap = {
64 | top: 0,
65 | middle: 1,
66 | bottom: 2
67 | }
68 |
69 | const start = typeMap[type] * dis
70 | const end = start + dis
71 | this.tracks.forEach((track, i) => {
72 | if (i >= start && i < end) {
73 | track.show()
74 | } else {
75 | if (type === 'bottom' && i >= end) track.show()
76 | else track.hidden()
77 | }
78 | })
79 | }
80 | }
--------------------------------------------------------------------------------
/src/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
77 |
78 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vue-custom-barrage
9 |
10 |
11 |
18 |
19 |
20 |
21 |
22 |
31 |
32 | {{ data }}
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | 发射数量:
44 |
45 |
46 | 发射速度:
47 |
48 |
49 | 发射延迟:
50 |
51 |
52 | 发射内容:
53 |
54 |
55 | 弹幕区域:
56 |
62 |
63 |
64 |
65 |
93 |
94 |
--------------------------------------------------------------------------------
/src/track.js:
--------------------------------------------------------------------------------
1 | import { createVueNode } from './extend'
2 |
3 | const getRandomNum = (start, end) => parseInt(Math.floor(Math.random() * (end - start + 1)) + start)
4 |
5 | export default class RunWay {
6 | constructor(top, instance, queue) {
7 | this.top = top
8 | this.instance = instance
9 | this.container = instance.$el
10 | this.queue = queue
11 | this.containerWidth = this.container.getBoundingClientRect().width
12 | this.isFree = true
13 | this.currentBullet = {}
14 | this.timer = null
15 | this.startTimer = null
16 | this.isHidden = false
17 | this.isPaused = false
18 | }
19 |
20 | show() {
21 | this.isHidden = false
22 | this.biubiu()
23 | }
24 |
25 | hidden() {
26 | this.isHidden = true
27 | this.biubiu()
28 | }
29 |
30 | pause() {
31 | if (this.isPaused) return
32 |
33 | clearTimeout(this.timer)
34 | clearTimeout(this.startTimer)
35 |
36 | const now = Date.now()
37 | const duration = now - this.currentBullet.nextStartTime
38 | this.currentBullet.sportTime += duration
39 | this.isPaused = true
40 | }
41 |
42 | start() {
43 | if (!this.isPaused) return
44 |
45 | this.isPaused = false
46 | const now = Date.now()
47 | this.currentBullet.nextStartTime = now
48 | this.startTimer = setTimeout(() => {
49 | this.isFree = true
50 | this.biubiu()
51 | }, this.currentBullet.freeTime - this.currentBullet.sportTime)
52 | }
53 |
54 | biubiu() {
55 | if (!this.queue.length || !this.isFree || this.isPaused || this.isHidden) return
56 |
57 | this.isFree = false
58 | const val = this.queue.shift()
59 |
60 | const BarrageVNode = createVueNode({
61 | class: `barrage-bullet ${this.instance.barrageClass}`,
62 | style: {
63 | ...this.instance.barrageStyle,
64 | top: `${this.top}px`
65 | },
66 | }, this.instance.$scopedSlots?.default?.(val) || val)
67 | const barrageInstance = new BarrageVNode().$mount()
68 |
69 | this.container.append(barrageInstance.$el)
70 |
71 | const { width: offsetWidth } = barrageInstance.$el.getBoundingClientRect()
72 | const w = offsetWidth + this.containerWidth
73 |
74 | let { speed, defer } = this.instance
75 | speed *= 1000
76 | defer *= 1000
77 |
78 | let time = speed
79 | const { total, start } = this.currentBullet
80 |
81 | if (total) {
82 | const duration = this.currentBullet.sportTime || (Date.now() - start)
83 | if (total > duration) {
84 | let sTime = total - duration
85 | sTime += offsetWidth / (this.containerWidth / sTime)
86 | time = Math.max(sTime, time)
87 | }
88 | }
89 |
90 | barrageInstance.$el.style.setProperty('--offset', `-${w}px`)
91 | barrageInstance.$el.style.setProperty('--time', `${time}ms`)
92 |
93 | const v = w / time
94 | const freeTime = offsetWidth / v
95 |
96 | this.currentBullet = {
97 | start: Date.now(),
98 | nextStartTime: Date.now(),
99 | sportTime: 0,
100 | freeTime,
101 | total: time,
102 | }
103 |
104 | this.timer = setTimeout(() => {
105 | this.isFree = true
106 | this.biubiu()
107 | }, freeTime + defer)
108 |
109 | barrageInstance.$el.onanimationend = () => requestAnimationFrame(() => {
110 | barrageInstance.$el.remove()
111 | barrageInstance.$el = null
112 | })
113 | }
114 | }
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Barrage=t():e.Barrage=t()}(self,(function(){return(()=>{var e={705:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var r=e(t);return t[2]?"@media ".concat(t[2]," {").concat(r,"}"):r})).join("")},t.i=function(e,r,n){"string"==typeof e&&(e=[[null,e,""]]);var a={};if(n)for(var i=0;i{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(705),a=r.n(n)()((function(e){return e[1]}));a.push([e.id,"\n@keyframes barrageMove {\nto {\r\n transform: translateX(var(--offset));\n}\n}\n.barrage-container {\r\n position: relative;\r\n overflow: hidden;\n}\n.barrage-bullet {\r\n position: absolute;\r\n display: inline-block;\r\n height: 20px;\r\n top: 0;;\r\n left: 100%;\r\n white-space: nowrap;\r\n animation-name: barrageMove;\r\n animation-timing-function: linear;\r\n animation-play-state: var(--playState);\r\n animation-duration: var(--time);\n}\n.barrage-container-touch .barrage-bullet:hover {\r\n cursor: pointer;\r\n animation-play-state: paused;\r\n z-index: 1;\n}\r\n\r\n",""]);const i=a},916:(e,t,r)=>{var n=r(52);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,r(23).Z)("ee106b32",n,!1,{})},23:(e,t,r)=>{"use strict";function n(e,t){for(var r=[],n={},a=0;ap});var a="undefined"!=typeof document;if("undefined"!=typeof DEBUG&&DEBUG&&!a)throw new Error("vue-style-loader cannot be used in a non-browser environment. Use { target: 'node' } in your Webpack config to indicate a server-rendering environment.");var i={},o=a&&(document.head||document.getElementsByTagName("head")[0]),s=null,u=0,l=!1,c=function(){},f=null,d="data-vue-ssr-id",h="undefined"!=typeof navigator&&/msie [6-9]\b/.test(navigator.userAgent.toLowerCase());function p(e,t,r,a){l=r,f=a||{};var o=n(e,t);return y(o),function(t){for(var r=[],a=0;ar.parts.length&&(n.parts.length=r.parts.length)}else{var o=[];for(a=0;a{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};return(()=>{"use strict";r.d(n,{default:()=>b,L:()=>m});var e=function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{class:{"barrage-container":!0,"barrage-container-touch":e.touchPause}})};function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var r=1;rb){var g=y-b;g+=u/(this.containerWidth/g),h=Math.max(g,h)}}s.$el.style.setProperty("--offset","-".concat(l,"px")),s.$el.style.setProperty("--time","".concat(h,"ms"));var w=u/(l/h);this.currentBullet={start:Date.now(),nextStartTime:Date.now(),sportTime:0,freeTime:w,total:h},this.timer=setTimeout((function(){r.isFree=!0,r.biubiu()}),w+d),s.$el.onanimationend=function(){return requestAnimationFrame((function(){s.$el.remove(),s.$el=null}))}}}}])&&o(t.prototype,r),e}();function u(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=l(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,a=function(){};return{s:a,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:a}}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 i,o=!0,s=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return o=e.done,e},e:function(e){s=!0,i=e},f:function(){try{o||null==r.return||r.return()}finally{if(s)throw i}}}}function l(e,t){if(e){if("string"==typeof e)return c(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?c(e,t):void 0}}function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r=r&&a=n?t.show():t.hidden()}))}else{var a,i=u(this.tracks);try{for(i.s();!(a=i.n()).done;)a.value.show()}catch(e){i.e(e)}finally{i.f()}}}}])&&f(t.prototype,r),e}();function h(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r{var e={705:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var r=e(t);return t[2]?"@media ".concat(t[2]," {").concat(r,"}"):r})).join("")},t.i=function(e,r,n){"string"==typeof e&&(e=[[null,e,""]]);var a={};if(n)for(var i=0;i{"use strict";r.r(t),r.d(t,{default:()=>i});var n=r(705),a=r.n(n)()((function(e){return e[1]}));a.push([e.id,"\n@keyframes barrageMove {\nto {\r\n transform: translateX(var(--offset));\n}\n}\n.barrage-container {\r\n position: relative;\r\n overflow: hidden;\n}\n.barrage-bullet {\r\n position: absolute;\r\n display: inline-block;\r\n height: 20px;\r\n top: 0;;\r\n left: 100%;\r\n white-space: nowrap;\r\n animation-name: barrageMove;\r\n animation-timing-function: linear;\r\n animation-play-state: var(--playState);\r\n animation-duration: var(--time);\n}\n.barrage-container-touch .barrage-bullet:hover {\r\n cursor: pointer;\r\n animation-play-state: paused;\r\n z-index: 1;\n}\r\n\r\n",""]);const i=a},916:(e,t,r)=>{var n=r(52);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,r(23).Z)("ee106b32",n,!1,{})},23:(e,t,r)=>{"use strict";function n(e,t){for(var r=[],n={},a=0;ap});var a="undefined"!=typeof document;if("undefined"!=typeof DEBUG&&DEBUG&&!a)throw new Error("vue-style-loader cannot be used in a non-browser environment. Use { target: 'node' } in your Webpack config to indicate a server-rendering environment.");var i={},o=a&&(document.head||document.getElementsByTagName("head")[0]),s=null,u=0,l=!1,c=function(){},f=null,d="data-vue-ssr-id",h="undefined"!=typeof navigator&&/msie [6-9]\b/.test(navigator.userAgent.toLowerCase());function p(e,t,r,a){l=r,f=a||{};var o=n(e,t);return y(o),function(t){for(var r=[],a=0;ar.parts.length&&(n.parts.length=r.parts.length)}else{var o=[];for(a=0;a{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};return(()=>{"use strict";r.d(n,{default:()=>b,L:()=>m});var e=function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{class:{"barrage-container":!0,"barrage-container-touch":e.touchPause}})};function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var r=1;rb){var g=y-b;g+=u/(this.containerWidth/g),h=Math.max(g,h)}}s.$el.style.setProperty("--offset","-".concat(l,"px")),s.$el.style.setProperty("--time","".concat(h,"ms"));var w=u/(l/h);this.currentBullet={start:Date.now(),nextStartTime:Date.now(),sportTime:0,freeTime:w,total:h},this.timer=setTimeout((function(){r.isFree=!0,r.biubiu()}),w+d),s.$el.onanimationend=function(){return requestAnimationFrame((function(){s.$el.remove(),s.$el=null}))}}}}])&&o(t.prototype,r),e}();function u(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=l(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,a=function(){};return{s:a,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:a}}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 i,o=!0,s=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return o=e.done,e},e:function(e){s=!0,i=e},f:function(){try{o||null==r.return||r.return()}finally{if(s)throw i}}}}function l(e,t){if(e){if("string"==typeof e)return c(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?c(e,t):void 0}}function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r=r&&a=n?t.show():t.hidden()}))}else{var a,i=u(this.tracks);try{for(i.s();!(a=i.n()).done;)a.value.show()}catch(e){i.e(e)}finally{i.f()}}}}])&&f(t.prototype,r),e}();function h(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r