├── .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 | 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 | 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 | 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