mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-17 18:11:20 -08:00
feat: add danmuku plugin documentation and i18n setup guide - Created a new documentation file for the danmuku plugin with code examples. - Added a comprehensive guide for language settings (i18n) including default languages, importing languages, adding new languages, and modifying existing languages. - Included code snippets for initializing the Artplayer with different language settings. Add internationalization support for multiple languages in Artplayer - Introduced Arabic (ar), Czech (cs), Spanish (es), Persian (fa), French (fr), Indonesian (id), Polish (pl), Russian (ru), Turkish (tr), Vietnamese (vi), and Traditional Chinese (zh-tw) translations. - Created corresponding JavaScript and ES module files for each language containing translated strings for player controls and settings. - Added a new documentation file for language settings in the project. feat: add initial implementation of start option page with interactive code execution buttons feat: add danmuku plugin documentation and i18n setup guide - Created a new documentation file for the danmuku plugin, providing code examples for usage. - Added a comprehensive guide for language settings, including default languages, importing languages, adding new languages, and modifying existing languages. - Included code snippets for initializing the Artplayer with different language settings and importing language files. refactor: update danmuku worker implementation and remove unused i18n files - Changed the way the Danmuku class creates a Web Worker by using a worker loader instead of creating a blob. - Removed Arabic, Czech, Spanish, Persian, French, Indonesian, Polish, Russian, Turkish, Vietnamese, and Traditional Chinese i18n files as they are no longer needed. - Updated the Vite build configuration to disable banners for inline workers and added a plugin to remove worker banners from generated code. feat: add danmuku plugin and i18n setup documentation - Created a new documentation file for the danmuku plugin, providing code examples for usage. - Added a new documentation file for language settings (i18n), detailing how to set default languages, import languages, and add new languages. - Included code snippets for initializing the Artplayer with different language settings and examples for modifying existing languages. feat: add danmuku plugin and i18n setup documentation - Created a new documentation file for the danmuku plugin with code examples. - Added a new documentation file for language settings (i18n) including import instructions and examples for setting default and custom languages. - Updated the i18n documentation to include details on adding and modifying languages. feat: add danmuku plugin and i18n setup documentation - Created a new JavaScript file for the danmuku plugin documentation with multiple code execution buttons. - Added a new JavaScript file for i18n (internationalization) setup documentation, including instructions for language settings, importing languages, and modifying language options. - Included examples for setting default languages and adding new languages in the i18n documentation. Refactor code structure for improved readability and maintainability
766 lines
21 KiB
JavaScript
766 lines
21 KiB
JavaScript
import $check_off from './img/check_off.svg?raw'
|
|
import $check_on from './img/check_on.svg?raw'
|
|
import $config from './img/config.svg?raw'
|
|
import $mode_0_off from './img/mode_0_off.svg?raw'
|
|
import $mode_0_on from './img/mode_0_on.svg?raw'
|
|
import $mode_1_off from './img/mode_1_off.svg?raw'
|
|
import $mode_1_on from './img/mode_1_on.svg?raw'
|
|
import $mode_2_off from './img/mode_2_off.svg?raw'
|
|
import $mode_2_on from './img/mode_2_on.svg?raw'
|
|
import $off from './img/off.svg?raw'
|
|
import $on from './img/on.svg?raw'
|
|
import $style from './img/style.svg?raw'
|
|
import style from './style.less?inline'
|
|
|
|
export default class Setting {
|
|
constructor(art, danmuku) {
|
|
this.art = art
|
|
this.danmuku = danmuku
|
|
this.utils = art.constructor.utils
|
|
|
|
const { setStyle } = this.utils
|
|
const { $controlsCenter } = art.template
|
|
setStyle($controlsCenter, 'display', 'flex')
|
|
|
|
this.template = {
|
|
$controlsCenter,
|
|
$mount: $controlsCenter,
|
|
$danmuku: null,
|
|
$toggle: null,
|
|
$config: null,
|
|
$configPanel: null,
|
|
$configModes: null,
|
|
$style: null,
|
|
$stylePanel: null,
|
|
$styleModes: null,
|
|
$colors: null,
|
|
$opacitySlider: null,
|
|
$opacityValue: null,
|
|
$marginSlider: null,
|
|
$marginValue: null,
|
|
$fontSizeSlider: null,
|
|
$fontSizeValue: null,
|
|
$speedSlider: null,
|
|
$speedValue: null,
|
|
$input: null,
|
|
$send: null,
|
|
}
|
|
|
|
this.slider = {
|
|
opacity: null,
|
|
margin: null,
|
|
fontSize: null,
|
|
speed: null,
|
|
}
|
|
|
|
this.emitting = false
|
|
this.isLock = false
|
|
this.timer = null
|
|
|
|
this.createTemplate()
|
|
this.createSliders()
|
|
this.createEvents()
|
|
|
|
this.mount(this.option.mount)
|
|
|
|
art.on('resize', () => this.resize())
|
|
art.on('fullscreen', state => this.onFullscreen(state))
|
|
art.on('fullscreenWeb', state => this.onFullscreen(state))
|
|
|
|
art.proxy(this.template.$config, 'mouseenter', () => {
|
|
this.onMouseEnter({
|
|
$control: this.template.$config,
|
|
$panel: this.template.$configPanel,
|
|
})
|
|
})
|
|
|
|
art.proxy(this.template.$style, 'mouseenter', () => {
|
|
this.onMouseEnter({
|
|
$control: this.template.$style,
|
|
$panel: this.template.$stylePanel,
|
|
})
|
|
})
|
|
}
|
|
|
|
static get icons() {
|
|
return {
|
|
$on,
|
|
$off,
|
|
$config,
|
|
$style,
|
|
$mode_0_off,
|
|
$mode_0_on,
|
|
$mode_1_off,
|
|
$mode_1_on,
|
|
$mode_2_off,
|
|
$mode_2_on,
|
|
$check_on,
|
|
$check_off,
|
|
}
|
|
}
|
|
|
|
get option() {
|
|
return this.danmuku.option
|
|
}
|
|
|
|
get outside() {
|
|
return this.template.$mount !== this.template.$controlsCenter
|
|
}
|
|
|
|
get TEMPLATE() {
|
|
const { option } = this
|
|
return `
|
|
<div class="apd-toggle">
|
|
${$on}${$off}
|
|
</div>
|
|
<div class="apd-config">
|
|
${$config}
|
|
<div class="apd-config-panel">
|
|
<div class="apd-config-panel-inner">
|
|
<div class="apd-config-mode">
|
|
按类型屏蔽
|
|
<div class="apd-modes">
|
|
<div data-mode="0" class="apd-mode">
|
|
${$mode_0_off}${$mode_0_on}
|
|
<div>滚动</div>
|
|
</div>
|
|
<div data-mode="1" class="apd-mode">
|
|
${$mode_1_off}${$mode_1_on}
|
|
<div>顶部</div>
|
|
</div>
|
|
<div data-mode="2" class="apd-mode">
|
|
${$mode_2_off}${$mode_2_on}
|
|
<div>底部</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="apd-config-other">
|
|
<div class="apd-other apd-anti-overlap">
|
|
${$check_on}${$check_off}
|
|
防止弹幕重叠
|
|
</div>
|
|
<div class="apd-other apd-sync-video">
|
|
${$check_on}${$check_off}
|
|
同步视频速度
|
|
</div>
|
|
</div>
|
|
<div class="apd-config-slider apd-config-opacity">
|
|
不透明度
|
|
<div class="apd-slider"></div>
|
|
<div class="apd-value">未知</div>
|
|
</div>
|
|
<div class="apd-config-slider apd-config-margin">
|
|
显示区域
|
|
<div class="apd-slider"></div>
|
|
<div class="apd-value">未知</div>
|
|
</div>
|
|
<div class="apd-config-slider apd-config-fontSize">
|
|
弹幕字号
|
|
<div class="apd-slider"></div>
|
|
<div class="apd-value">未知</div>
|
|
</div>
|
|
<div class="apd-config-slider apd-config-speed">
|
|
弹幕速度
|
|
<div class="apd-slider"></div>
|
|
<div class="apd-value">未知</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="apd-emitter">
|
|
<div class="apd-style">
|
|
${$style}
|
|
<div class="apd-style-panel">
|
|
<div class="apd-style-panel-inner">
|
|
<div class="apd-style-mode">
|
|
模式
|
|
<div class="apd-modes">
|
|
<div data-mode="0" class="apd-mode">
|
|
${$mode_0_on}
|
|
<div>滚动</div>
|
|
</div>
|
|
<div data-mode="1" class="apd-mode">
|
|
${$mode_1_on}
|
|
<div>顶部</div>
|
|
</div>
|
|
<div data-mode="2" class="apd-mode">
|
|
${$mode_2_on}
|
|
<div>底部</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="apd-style-color">
|
|
颜色
|
|
<div class="apd-colors">
|
|
${this.COLOR.map(color => `<div data-color="${color}" class="apd-color" style="background-color: ${color}"></div>`).join('')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<input class="apd-input" placeholder="发个友善的弹幕见证当下" autocomplete="off" maxLength="${option.maxLength}" />
|
|
<div class="apd-send">发送</div>
|
|
</div>
|
|
`
|
|
}
|
|
|
|
get OPACITY() {
|
|
return {
|
|
min: 0,
|
|
max: 100,
|
|
steps: [],
|
|
...this.option.OPACITY,
|
|
}
|
|
}
|
|
|
|
get FONT_SIZE() {
|
|
return {
|
|
min: 12,
|
|
max: 120,
|
|
steps: [],
|
|
...this.option.FONT_SIZE,
|
|
}
|
|
}
|
|
|
|
get MARGIN() {
|
|
return {
|
|
min: 0,
|
|
max: 3,
|
|
steps: [
|
|
{
|
|
name: '1/4',
|
|
value: [10, '75%'],
|
|
},
|
|
{
|
|
name: '半屏',
|
|
value: [10, '50%'],
|
|
},
|
|
{
|
|
name: '3/4',
|
|
value: [10, '25%'],
|
|
},
|
|
{
|
|
name: '满屏',
|
|
value: [10, 10],
|
|
},
|
|
],
|
|
...this.option.MARGIN,
|
|
}
|
|
}
|
|
|
|
get SPEED() {
|
|
return {
|
|
min: 0,
|
|
max: 4,
|
|
steps: [
|
|
{
|
|
name: '极慢',
|
|
value: 10,
|
|
},
|
|
{
|
|
name: '较慢',
|
|
value: 7.5,
|
|
hide: true,
|
|
},
|
|
{
|
|
name: '适中',
|
|
value: 5,
|
|
},
|
|
{
|
|
name: '较快',
|
|
value: 2.5,
|
|
hide: true,
|
|
},
|
|
{
|
|
name: '极快',
|
|
value: 1,
|
|
},
|
|
],
|
|
...this.option.SPEED,
|
|
}
|
|
}
|
|
|
|
get COLOR() {
|
|
return this.option.COLOR.length
|
|
? this.option.COLOR
|
|
: [
|
|
'#FE0302',
|
|
'#FF7204',
|
|
'#FFAA02',
|
|
'#FFD302',
|
|
'#FFFF00',
|
|
'#A0EE00',
|
|
'#00CD00',
|
|
'#019899',
|
|
'#4266BE',
|
|
'#89D5FF',
|
|
'#CC0273',
|
|
'#222222',
|
|
'#9B9B9B',
|
|
'#FFFFFF',
|
|
]
|
|
}
|
|
|
|
query(selector) {
|
|
const { query } = this.utils
|
|
const { $danmuku } = this.template
|
|
return query(selector, $danmuku)
|
|
}
|
|
|
|
append(el, target) {
|
|
const { append } = this.utils
|
|
const children = [...el.children]
|
|
if (children.includes(target))
|
|
return
|
|
append(el, target)
|
|
}
|
|
|
|
setData(key, value) {
|
|
const { $player } = this.art.template
|
|
const { $mount } = this.template
|
|
$player.dataset[key] = value
|
|
if (this.outside) {
|
|
$mount.dataset[key] = value
|
|
}
|
|
}
|
|
|
|
createTemplate() {
|
|
const { createElement, tooltip } = this.utils
|
|
|
|
const $danmuku = createElement('div')
|
|
$danmuku.className = 'artplayer-plugin-danmuku'
|
|
$danmuku.innerHTML = this.TEMPLATE
|
|
|
|
this.template.$danmuku = $danmuku
|
|
this.template.$toggle = this.query('.apd-toggle')
|
|
this.template.$config = this.query('.apd-config')
|
|
this.template.$configPanel = this.query('.apd-config-panel')
|
|
this.template.$configModes = this.query('.apd-config-mode .apd-modes')
|
|
this.template.$style = this.query('.apd-style')
|
|
this.template.$stylePanel = this.query('.apd-style-panel')
|
|
this.template.$styleModes = this.query('.apd-style-mode .apd-modes')
|
|
this.template.$colors = this.query('.apd-colors')
|
|
this.template.$antiOverlap = this.query('.apd-anti-overlap')
|
|
this.template.$syncVideo = this.query('.apd-sync-video')
|
|
this.template.$opacitySlider = this.query('.apd-config-opacity .apd-slider')
|
|
this.template.$opacityValue = this.query('.apd-config-opacity .apd-value')
|
|
this.template.$marginSlider = this.query('.apd-config-margin .apd-slider')
|
|
this.template.$marginValue = this.query('.apd-config-margin .apd-value')
|
|
this.template.$fontSizeSlider = this.query('.apd-config-fontSize .apd-slider')
|
|
this.template.$fontSizeValue = this.query('.apd-config-fontSize .apd-value')
|
|
this.template.$speedSlider = this.query('.apd-config-speed .apd-slider')
|
|
this.template.$speedValue = this.query('.apd-config-speed .apd-value')
|
|
this.template.$input = this.query('.apd-input')
|
|
this.template.$send = this.query('.apd-send')
|
|
|
|
const { $toggle } = this.template
|
|
|
|
this.art.on('artplayerPluginDanmuku:show', () => {
|
|
tooltip($toggle, '关闭弹幕')
|
|
})
|
|
|
|
this.art.on('artplayerPluginDanmuku:hide', () => {
|
|
tooltip($toggle, '打开弹幕')
|
|
})
|
|
}
|
|
|
|
createEvents() {
|
|
const { $toggle, $configModes, $styleModes, $colors, $antiOverlap, $syncVideo, $send, $input } = this.template
|
|
|
|
this.art.proxy($toggle, 'click', () => {
|
|
this.danmuku.config({
|
|
visible: !this.option.visible,
|
|
})
|
|
this.reset()
|
|
})
|
|
|
|
this.art.proxy($configModes, 'click', (event) => {
|
|
const $mode = event.target.closest('.apd-mode')
|
|
if (!$mode)
|
|
return
|
|
const mode = Number($mode.dataset.mode)
|
|
if (this.option.modes.includes(mode)) {
|
|
this.danmuku.config({
|
|
modes: this.option.modes.filter(m => m !== mode),
|
|
})
|
|
}
|
|
else {
|
|
this.danmuku.config({
|
|
modes: [...this.option.modes, mode],
|
|
})
|
|
}
|
|
this.reset()
|
|
})
|
|
|
|
this.art.proxy($antiOverlap, 'click', () => {
|
|
this.danmuku.config({
|
|
antiOverlap: !this.option.antiOverlap,
|
|
})
|
|
this.reset()
|
|
})
|
|
|
|
this.art.proxy($syncVideo, 'click', () => {
|
|
this.danmuku.config({
|
|
synchronousPlayback: !this.option.synchronousPlayback,
|
|
})
|
|
this.reset()
|
|
})
|
|
|
|
this.art.proxy($styleModes, 'click', (event) => {
|
|
const $mode = event.target.closest('.apd-mode')
|
|
if (!$mode)
|
|
return
|
|
const mode = Number($mode.dataset.mode)
|
|
this.danmuku.config({
|
|
mode,
|
|
})
|
|
this.reset()
|
|
})
|
|
|
|
this.art.proxy($colors, 'click', (event) => {
|
|
const $color = event.target.closest('.apd-color')
|
|
if (!$color)
|
|
return
|
|
this.danmuku.config({
|
|
color: $color.dataset.color,
|
|
})
|
|
this.reset()
|
|
})
|
|
|
|
this.art.proxy($send, 'click', () => this.emit())
|
|
|
|
this.art.proxy($input, 'keypress', (event) => {
|
|
if (event.key === 'Enter') {
|
|
event.preventDefault()
|
|
this.emit()
|
|
}
|
|
})
|
|
}
|
|
|
|
createSliders() {
|
|
this.slider.opacity = this.createSlider({
|
|
...this.OPACITY,
|
|
container: this.template.$opacitySlider,
|
|
findIndex: () => {
|
|
return Math.round(this.option.opacity * 100)
|
|
},
|
|
onChange: (index) => {
|
|
const { $opacityValue } = this.template
|
|
$opacityValue.textContent = `${index}%`
|
|
this.danmuku.config({
|
|
opacity: index / 100,
|
|
})
|
|
},
|
|
})
|
|
|
|
this.slider.margin = this.createSlider({
|
|
...this.MARGIN,
|
|
container: this.template.$marginSlider,
|
|
findIndex: () => {
|
|
return this.MARGIN.steps.findIndex(
|
|
item => item.value[0] === this.option.margin[0] && item.value[1] === this.option.margin[1],
|
|
)
|
|
},
|
|
onChange: (index) => {
|
|
const margin = this.MARGIN.steps[index]
|
|
if (!margin)
|
|
return
|
|
const { $marginValue } = this.template
|
|
$marginValue.textContent = margin.name
|
|
this.danmuku.config({
|
|
margin: margin.value,
|
|
})
|
|
},
|
|
})
|
|
|
|
this.slider.fontSize = this.createSlider({
|
|
...this.FONT_SIZE,
|
|
container: this.template.$fontSizeSlider,
|
|
findIndex: () => {
|
|
return this.danmuku.fontSize
|
|
},
|
|
onChange: (index) => {
|
|
const { $fontSizeValue } = this.template
|
|
$fontSizeValue.textContent = `${index}px`
|
|
if (index === this.danmuku.fontSize)
|
|
return
|
|
this.danmuku.config({
|
|
fontSize: index,
|
|
})
|
|
},
|
|
})
|
|
|
|
this.slider.speed = this.createSlider({
|
|
...this.SPEED,
|
|
container: this.template.$speedSlider,
|
|
findIndex: () => {
|
|
return this.SPEED.steps.findIndex(item => item.value === this.option.speed)
|
|
},
|
|
onChange: (index) => {
|
|
const speed = this.SPEED.steps[index]
|
|
if (!speed)
|
|
return
|
|
const { $speedValue } = this.template
|
|
$speedValue.textContent = speed.name
|
|
this.danmuku.config({
|
|
speed: speed.value,
|
|
})
|
|
},
|
|
})
|
|
}
|
|
|
|
createSlider({ min, max, container, findIndex, onChange, steps = [] }) {
|
|
const { query, clamp, setStyle } = this.utils
|
|
|
|
setStyle(container, 'touch-action', 'none')
|
|
|
|
container.innerHTML = `
|
|
<div class="apd-slider-line">
|
|
<div class="apd-slider-points">
|
|
${steps.map(() => `<div class="apd-slider-point"></div>`).join('')}
|
|
</div>
|
|
<div class="apd-slider-progress"></div>
|
|
</div>
|
|
<div class="apd-slider-dot"></div>
|
|
<div class="apd-slider-steps">
|
|
${steps.map(step => (step.hide ? '' : `<div class="apd-slider-step">${step.name}</div>`)).join('')}
|
|
</div>
|
|
`
|
|
|
|
const $dot = query('.apd-slider-dot', container)
|
|
const $progress = query('.apd-slider-progress', container)
|
|
|
|
let isDroging = false
|
|
|
|
function reset(index = findIndex()) {
|
|
if (index < min || index > max)
|
|
return
|
|
const percentage = (index - min) / (max - min)
|
|
$dot.style.left = `${percentage * 100}%`
|
|
if (steps.length === 0) {
|
|
$progress.style.width = $dot.style.left
|
|
}
|
|
onChange(index)
|
|
}
|
|
|
|
function updateLeft(event) {
|
|
const { top, height, left, width } = container.getBoundingClientRect()
|
|
if (this.art.isRotate) {
|
|
const value = clamp(event.clientY - top, 0, height)
|
|
const index = Math.round((value / height) * (max - min) + min)
|
|
reset(index)
|
|
}
|
|
else {
|
|
const value = clamp(event.clientX - left, 0, width)
|
|
const index = Math.round((value / width) * (max - min) + min)
|
|
reset(index)
|
|
}
|
|
}
|
|
|
|
this.art.proxy(container, 'click', (event) => {
|
|
updateLeft.call(this, event)
|
|
})
|
|
|
|
this.art.proxy(container, 'pointerdown', (event) => {
|
|
isDroging = event.button === 0
|
|
})
|
|
|
|
this.art.on('document:pointermove', (event) => {
|
|
if (isDroging) {
|
|
updateLeft.call(this, event)
|
|
}
|
|
})
|
|
|
|
this.art.on('document:pointerup', (event) => {
|
|
if (isDroging) {
|
|
isDroging = false
|
|
updateLeft.call(this, event)
|
|
}
|
|
})
|
|
|
|
return { reset }
|
|
}
|
|
|
|
onFullscreen(state) {
|
|
const { $danmuku, $controlsCenter, $mount } = this.template
|
|
if (this.outside) {
|
|
if (state) {
|
|
this.append($controlsCenter, $danmuku)
|
|
}
|
|
else {
|
|
this.append($mount, $danmuku)
|
|
}
|
|
}
|
|
else {
|
|
this.append($controlsCenter, $danmuku)
|
|
}
|
|
}
|
|
|
|
onMouseEnter({ $control, $panel }) {
|
|
const { $player } = this.art.template
|
|
const controlRect = $control.getBoundingClientRect()
|
|
const panelRect = $panel.getBoundingClientRect()
|
|
const playerRect = $player.getBoundingClientRect()
|
|
|
|
const half = panelRect.width / 2 - controlRect.width / 2
|
|
const left = playerRect.left - (controlRect.left - half)
|
|
const right = controlRect.right + half - playerRect.right
|
|
|
|
if (left > 0) {
|
|
$panel.style.left = `${-half + left}px`
|
|
}
|
|
else if (right > 0) {
|
|
$panel.style.left = `${-half - right}px`
|
|
}
|
|
else {
|
|
$panel.style.left = `${-half}px`
|
|
}
|
|
}
|
|
|
|
async emit() {
|
|
const { $input } = this.template
|
|
|
|
const text = $input.value.trim()
|
|
if (!text.length)
|
|
return
|
|
if (this.isLock)
|
|
return
|
|
if (this.emitting)
|
|
return
|
|
|
|
const danmu = {
|
|
text,
|
|
mode: this.option.mode,
|
|
color: this.option.color,
|
|
time: this.art.currentTime,
|
|
}
|
|
|
|
try {
|
|
this.emitting = true
|
|
const state = await this.option.beforeEmit(danmu)
|
|
this.emitting = false
|
|
|
|
if (state !== true)
|
|
return
|
|
|
|
danmu.border = true
|
|
delete danmu.time
|
|
this.danmuku.emit(danmu)
|
|
$input.value = ''
|
|
|
|
this.lock()
|
|
}
|
|
catch (error) {
|
|
console.error('Error emitting danmuku:', error)
|
|
this.emitting = false
|
|
}
|
|
}
|
|
|
|
lock() {
|
|
const { addClass } = this.utils
|
|
const { $send } = this.template
|
|
|
|
this.isLock = true
|
|
let time = this.option.lockTime
|
|
$send.textContent = time
|
|
addClass($send, 'apd-lock')
|
|
|
|
const loop = () => {
|
|
this.timer = setTimeout(() => {
|
|
if (time === 0) {
|
|
this.unlock()
|
|
}
|
|
else {
|
|
time -= 1
|
|
$send.textContent = time
|
|
loop()
|
|
}
|
|
}, 1000)
|
|
}
|
|
|
|
loop()
|
|
}
|
|
|
|
unlock() {
|
|
const { removeClass } = this.utils
|
|
const { $send } = this.template
|
|
clearTimeout(this.timer)
|
|
this.isLock = false
|
|
$send.textContent = '发送'
|
|
removeClass($send, 'apd-lock')
|
|
}
|
|
|
|
resize() {
|
|
if (this.outside)
|
|
return
|
|
if (this.art.fullscreen)
|
|
return
|
|
if (this.art.fullscreenWeb)
|
|
return
|
|
const { $player, $controlsCenter } = this.art.template
|
|
const { $danmuku } = this.template
|
|
if (this.art.width < this.option.width) {
|
|
this.append($player, $danmuku)
|
|
}
|
|
else {
|
|
this.append($controlsCenter, $danmuku)
|
|
}
|
|
}
|
|
|
|
reset() {
|
|
const { inverseClass, tooltip } = this.utils
|
|
const { $toggle, $colors } = this.template
|
|
|
|
this.slider.opacity.reset()
|
|
this.slider.margin.reset()
|
|
this.slider.fontSize.reset()
|
|
this.slider.speed.reset()
|
|
|
|
this.setData('danmukuVisible', this.option.visible)
|
|
this.setData('danmukuMode', this.option.mode)
|
|
this.setData('danmukuColor', this.option.color)
|
|
this.setData('danmukuMode0', this.option.modes.includes(0))
|
|
this.setData('danmukuMode1', this.option.modes.includes(1))
|
|
this.setData('danmukuMode2', this.option.modes.includes(2))
|
|
this.setData('danmukuAntiOverlap', this.option.antiOverlap)
|
|
this.setData('danmukuSyncVideo', this.option.synchronousPlayback)
|
|
this.setData('danmukuTheme', this.option.theme)
|
|
this.setData('danmukuEmitter', this.option.emitter)
|
|
|
|
const colors = $colors.children
|
|
const $color = Array.from(colors).find(item => item.dataset.color === this.option.color.toUpperCase())
|
|
$color && inverseClass($color, 'apd-active')
|
|
|
|
tooltip($toggle, this.option.visible ? '关闭弹幕' : '打开弹幕')
|
|
|
|
this.resize()
|
|
}
|
|
|
|
mount(target) {
|
|
const { errorHandle } = this.utils
|
|
const $el = typeof target === 'string' ? document.querySelector(target) : target
|
|
errorHandle($el, `Can not find the mount point: ${target}`)
|
|
this.append($el, this.template.$danmuku)
|
|
this.template.$mount = $el
|
|
this.reset()
|
|
}
|
|
}
|
|
|
|
if (typeof document !== 'undefined') {
|
|
const id = 'artplayer-plugin-danmuku'
|
|
let $style = document.getElementById(id)
|
|
if (!$style) {
|
|
$style = document.createElement('style')
|
|
$style.id = id
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
document.head.appendChild($style)
|
|
})
|
|
}
|
|
else {
|
|
(document.head || document.documentElement).appendChild($style)
|
|
}
|
|
}
|
|
$style.textContent = style
|
|
}
|