Files
ArtPlayer/packages/artplayer/src/control/index.js
T

281 lines
7.3 KiB
JavaScript

import Component from '../utils/component';
import fullscreen from './fullscreen';
import fullscreenWeb from './fullscreenWeb';
import pip from './pip';
import playAndPause from './playAndPause';
import progress from './progress';
import time from './time';
import volume from './volume';
import setting from './setting';
import screenshot from './screenshot';
import airplay from './airplay';
import {
def,
sleep,
append,
addClass,
isMobile,
removeClass,
errorHandle,
inverseClass,
createElement,
includeFromEvent,
} from '../utils';
export default class Control extends Component {
constructor(art) {
super(art);
this.isHover = false;
this.name = 'control';
this.timer = Date.now();
const { constructor } = art;
const { $player, $bottom } = this.art.template;
art.on('mousemove', () => {
if (!isMobile) {
this.show = true;
}
});
art.on('click', () => {
if (isMobile) {
this.toggle();
} else {
this.show = true;
}
});
art.on('document:mousemove', (event) => {
this.isHover = includeFromEvent(event, $bottom);
});
art.on('video:timeupdate', () => {
if (
!art.setting.show &&
!this.isHover &&
!art.isInput &&
art.playing &&
this.show &&
Date.now() - this.timer >= constructor.CONTROL_HIDE_TIME
) {
this.show = false;
}
});
art.on('control', (state) => {
if (state) {
removeClass($player, 'art-hide-cursor');
addClass($player, 'art-hover');
this.timer = Date.now();
} else {
addClass($player, 'art-hide-cursor');
removeClass($player, 'art-hover');
}
});
this.init();
}
init() {
const { option } = this.art;
if (!option.isLive) {
this.add(
progress({
name: 'progress',
position: 'top',
index: 10,
}),
);
}
this.add({
name: 'thumbnails',
position: 'top',
index: 20,
});
this.add(
playAndPause({
name: 'playAndPause',
position: 'left',
index: 10,
}),
);
this.add(
volume({
name: 'volume',
position: 'left',
index: 20,
}),
);
if (!option.isLive) {
this.add(
time({
name: 'time',
position: 'left',
index: 30,
}),
);
}
if (option.quality.length) {
sleep().then(() => {
this.art.quality = option.quality;
});
}
if (option.screenshot && !isMobile) {
this.add(
screenshot({
name: 'screenshot',
position: 'right',
index: 20,
}),
);
}
if (option.setting) {
this.add(
setting({
name: 'setting',
position: 'right',
index: 30,
}),
);
}
if (option.pip) {
this.add(
pip({
name: 'pip',
position: 'right',
index: 40,
}),
);
}
if (option.airplay && window.WebKitPlaybackTargetAvailabilityEvent) {
this.add(
airplay({
name: 'airplay',
position: 'right',
index: 50,
}),
);
}
if (option.fullscreenWeb) {
this.add(
fullscreenWeb({
name: 'fullscreenWeb',
position: 'right',
index: 60,
}),
);
}
if (option.fullscreen) {
this.add(
fullscreen({
name: 'fullscreen',
position: 'right',
index: 70,
}),
);
}
for (let index = 0; index < option.controls.length; index++) {
this.add(option.controls[index]);
}
}
add(getOption) {
const option = typeof getOption === 'function' ? getOption(this.art) : getOption;
const { $progress, $controlsLeft, $controlsRight } = this.art.template;
switch (option.position) {
case 'top':
this.$parent = $progress;
break;
case 'left':
this.$parent = $controlsLeft;
break;
case 'right':
this.$parent = $controlsRight;
break;
default:
errorHandle(false, `Control option.position must one of 'top', 'left', 'right'`);
break;
}
super.add(option);
}
check(target) {
target.$control_value.innerHTML = target.html;
for (let index = 0; index < target.$control_option.length; index++) {
const item = target.$control_option[index];
item.default = item === target;
if (item.default) {
inverseClass(item.$control_item, 'art-current');
}
}
}
selector(option, $ref, events) {
const { proxy } = this.art.events;
addClass($ref, 'art-control-selector');
const $value = createElement('div');
addClass($value, 'art-selector-value');
append($value, option.html);
$ref.innerText = '';
append($ref, $value);
const $list = createElement('div');
addClass($list, 'art-selector-list');
append($ref, $list);
for (let index = 0; index < option.selector.length; index++) {
const item = option.selector[index];
const $item = createElement('div');
addClass($item, 'art-selector-item');
if (item.default) addClass($item, 'art-current');
$item.dataset.index = index;
$item.dataset.value = item.value;
$item.innerHTML = item.html;
append($list, $item);
def(item, '$control_option', {
get: () => option.selector,
});
def(item, '$control_item', {
get: () => $item,
});
def(item, '$control_value', {
get: () => $value,
});
}
const event = proxy($list, 'click', async (event) => {
const path = event.composedPath() || [];
const item = option.selector.find(
(item) => item.$control_item === path.find(($item) => item.$control_item === $item),
);
this.check(item);
if (option.onSelect) {
$value.innerHTML = await option.onSelect.call(this.art, item, item.$control_item, event);
}
});
events.push(event);
}
}