mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-16 09:36:16 -08:00
分离控制器功能
This commit is contained in:
1 parent
851303e530
commit
ca7e24a525
21 files changed
+539
-487
No files matched your search
@@ -1,49 +0,0 @@
|
||||
import { append, tooltip, setStyle } from '../utils';
|
||||
import icons from '../icons';
|
||||
|
||||
export default class FullscreenWeb {
|
||||
constructor(option) {
|
||||
this.option = option;
|
||||
this.state = false;
|
||||
}
|
||||
|
||||
apply(art, $control) {
|
||||
this.art = art;
|
||||
const { events: { proxy }, i18n, player, controls } = art;
|
||||
this.$fullscreenWeb = append($control, icons.fullscreenWeb);
|
||||
tooltip(this.$fullscreenWeb, i18n.get('Web fullscreen'));
|
||||
proxy($control, 'click', () => {
|
||||
if (controls.fullscreen && controls.fullscreen.state) {
|
||||
controls.fullscreen.exit();
|
||||
}
|
||||
|
||||
this.toggle();
|
||||
player.resetAspectRatio();
|
||||
art.emit('fullscreenWeb', this.state);
|
||||
});
|
||||
}
|
||||
|
||||
enabled() {
|
||||
const { i18n, refs: { $player } } = this.art;
|
||||
this.state = true;
|
||||
$player.classList.add('artplayer-web-fullscreen');
|
||||
setStyle(this.$fullscreenWeb, 'opacity', '0.8');
|
||||
tooltip(this.$fullscreenWeb, i18n.get('Exit web fullscreen'));
|
||||
}
|
||||
|
||||
exit() {
|
||||
const { i18n, refs: { $player } } = this.art;
|
||||
this.state = false;
|
||||
$player.classList.remove('artplayer-web-fullscreen');
|
||||
setStyle(this.$fullscreenWeb, 'opacity', '1');
|
||||
tooltip(this.$fullscreenWeb, i18n.get('Web fullscreen'));
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (this.state) {
|
||||
this.exit();
|
||||
} else {
|
||||
this.enabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,25 @@
|
||||
import { append, tooltip, setStyle } from '../utils';
|
||||
import icons from '../icons';
|
||||
import screenfull from 'screenfull';
|
||||
|
||||
export default class Fullscreen {
|
||||
constructor(option) {
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
get state() {
|
||||
return screenfull.isFullscreen;
|
||||
}
|
||||
|
||||
apply(art, $control) {
|
||||
this.art = art;
|
||||
const { events: { destroyEvents, proxy }, i18n, player, controls, notice } = art;
|
||||
const { events: { proxy }, i18n, player } = art;
|
||||
this.$fullscreen = append($control, icons.fullscreen);
|
||||
tooltip(this.$fullscreen, i18n.get('Fullscreen'));
|
||||
|
||||
proxy($control, 'click', () => {
|
||||
if (controls.fullscreenWeb && controls.fullscreenWeb.state) {
|
||||
controls.fullscreenWeb.exit();
|
||||
}
|
||||
|
||||
this.toggle();
|
||||
});
|
||||
|
||||
const screenfullChange = () => {
|
||||
player.resetAspectRatio();
|
||||
art.emit('fullscreen', screenfull.isFullscreen);
|
||||
};
|
||||
|
||||
const screenfullError = () => {
|
||||
notice.show('Your browser does not seem to support full screen functionality.');
|
||||
};
|
||||
|
||||
screenfull.on('change', screenfullChange);
|
||||
screenfull.on('error', screenfullError);
|
||||
destroyEvents.push(() => {
|
||||
screenfull.off('change', screenfullChange);
|
||||
screenfull.off('error', screenfullError);
|
||||
});
|
||||
}
|
||||
|
||||
enabled() {
|
||||
const { i18n, refs: { $player } } = this.art;
|
||||
$player.classList.add('artplayer-fullscreen');
|
||||
setStyle(this.$fullscreen, 'opacity', '0.8');
|
||||
tooltip(this.$fullscreen, i18n.get('Exit fullscreen'));
|
||||
screenfull.request($player);
|
||||
}
|
||||
|
||||
exit() {
|
||||
const { i18n, refs: { $player } } = this.art;
|
||||
$player.classList.remove('artplayer-fullscreen');
|
||||
setStyle(this.$fullscreen, 'opacity', '1');
|
||||
tooltip(this.$fullscreen, i18n.get('Fullscreen'));
|
||||
screenfull.exit();
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isFullscreen) {
|
||||
this.exit();
|
||||
if (player.fullscreenState) {
|
||||
player.fullscreenExit();
|
||||
setStyle(this.$fullscreen, 'opacity', '1');
|
||||
tooltip(this.$fullscreen, i18n.get('Fullscreen'));
|
||||
} else {
|
||||
this.enabled();
|
||||
player.fullscreenEnabled();
|
||||
setStyle(this.$fullscreen, 'opacity', '0.8');
|
||||
tooltip(this.$fullscreen, i18n.get('Exit fullscreen'));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { append, tooltip, setStyle } from '../utils';
|
||||
import icons from '../icons';
|
||||
|
||||
export default class FullscreenWeb {
|
||||
constructor(option) {
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
apply(art, $control) {
|
||||
const { events: { proxy }, i18n, player } = art;
|
||||
this.$fullscreenWeb = append($control, icons.fullscreenWeb);
|
||||
tooltip(this.$fullscreenWeb, i18n.get('Web fullscreen'));
|
||||
proxy($control, 'click', () => {
|
||||
if (player.fullscreenWebState) {
|
||||
player.fullscreenWebExit();
|
||||
setStyle(this.$fullscreenWeb, 'opacity', '1');
|
||||
tooltip(this.$fullscreenWeb, i18n.get('Web fullscreen'));
|
||||
} else {
|
||||
player.fullscreenWebEnabled();
|
||||
setStyle(this.$fullscreenWeb, 'opacity', '0.8');
|
||||
tooltip(this.$fullscreenWeb, i18n.get('Exit web fullscreen'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { setStyle, append } from '../utils';
|
||||
import Danmu from './danmu';
|
||||
import Fullscreen from './fullscreen';
|
||||
import FullscreenWeb from './fullscreen-web';
|
||||
import FullscreenWeb from './fullscreenWeb';
|
||||
import Pip from './pip';
|
||||
import PlayAndPause from './playAndPause';
|
||||
import Progress from './progress';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { append, tooltip, secondToTime, setStyle } from '../utils';
|
||||
import { append, tooltip } from '../utils';
|
||||
import icons from '../icons';
|
||||
|
||||
export default class Screenshot {
|
||||
@@ -7,33 +7,11 @@ export default class Screenshot {
|
||||
}
|
||||
|
||||
apply(art, $control) {
|
||||
this.art = art;
|
||||
const { events: { proxy }, i18n, notice } = this.art;
|
||||
const { events: { proxy }, i18n, player } = art;
|
||||
this.$screenshot = append($control, icons.screenshot);
|
||||
tooltip(this.$screenshot, i18n.get('Screenshot'));
|
||||
proxy(this.$screenshot, 'click', () => {
|
||||
try {
|
||||
this.captureFrame();
|
||||
art.emit('screenshot');
|
||||
} catch (error) {
|
||||
notice.show(error);
|
||||
}
|
||||
player.screenshot();
|
||||
});
|
||||
}
|
||||
|
||||
captureFrame() {
|
||||
const { $video } = this.art.refs;
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = $video.videoWidth;
|
||||
canvas.height = $video.videoHeight;
|
||||
canvas.getContext('2d').drawImage($video, 0, 0);
|
||||
const dataUri = canvas.toDataURL('image/png');
|
||||
const elink = document.createElement('a');
|
||||
setStyle(elink, 'display', 'none');
|
||||
elink.href = dataUri;
|
||||
elink.download = `ArtPlayer_${secondToTime($video.currentTime)}.png`;
|
||||
document.body.appendChild(elink);
|
||||
elink.click();
|
||||
document.body.removeChild(elink);
|
||||
}
|
||||
}
|
||||
@@ -15,12 +15,10 @@ export default class Setting {
|
||||
setting.hide();
|
||||
setStyle(this.$setting, 'opacity', '1');
|
||||
tooltip(this.$setting, i18n.get('Show setting'));
|
||||
art.emit('setting:hide');
|
||||
} else {
|
||||
setting.show();
|
||||
setStyle(this.$setting, 'opacity', '0.8');
|
||||
tooltip(this.$setting, i18n.get('Hide setting'));
|
||||
art.emit('setting:show');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,12 +15,10 @@ export default class Subtitle {
|
||||
subtitle.hide();
|
||||
setStyle(this.$subtitle, 'opacity', '1');
|
||||
tooltip(this.$subtitle, i18n.get('Show subtitle'));
|
||||
art.emit('subtitle:hide');
|
||||
} else {
|
||||
subtitle.show();
|
||||
setStyle(this.$subtitle, 'opacity', '0.8');
|
||||
tooltip(this.$subtitle, i18n.get('Hide subtitle'));
|
||||
art.emit('subtitle:show');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { setStyle, sublings } from '../utils';
|
||||
|
||||
export default function aspectRatioMix(art, player) {
|
||||
const { refs: { $video, $player }, i18n, notice, contextmenu } = art;
|
||||
|
||||
Object.defineProperty(player, 'aspectRatio', {
|
||||
value: ratio => {
|
||||
const { refs: { $video, $player }, i18n, notice } = art;
|
||||
const ratioName = ratio.length === 2 ? `${ratio[0]}:${ratio[1]}` : i18n.get('Default');
|
||||
|
||||
if (ratio.length === 2) {
|
||||
@@ -37,23 +38,21 @@ export default function aspectRatioMix(art, player) {
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'removeAspectRatio', {
|
||||
Object.defineProperty(player, 'aspectRatioRemove', {
|
||||
value: () => {
|
||||
const { refs: { $video }, contextmenu: { $aspectRatio } } = art;
|
||||
setStyle($video, 'width', null);
|
||||
setStyle($video, 'height', null);
|
||||
setStyle($video, 'padding', null);
|
||||
if ($aspectRatio) {
|
||||
const $default = $aspectRatio.querySelector('.default');
|
||||
if (contextmenu.$aspectRatio) {
|
||||
const $default = contextmenu.$aspectRatio.querySelector('.default');
|
||||
sublings($default).forEach(item => item.classList.remove('current'));
|
||||
$default.classList.add('current');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'resetAspectRatio', {
|
||||
Object.defineProperty(player, 'aspectRatioReset', {
|
||||
value: () => {
|
||||
const { refs: { $player } } = art;
|
||||
const { aspectRatio } = $player.dataset;
|
||||
if (aspectRatio) {
|
||||
player.aspectRatio(aspectRatio.split(':'));
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import screenfull from 'screenfull';
|
||||
|
||||
export default function fullscreenMix(art, player) {
|
||||
const { notice, events: { destroyEvents }, refs: { $player } } = art;
|
||||
|
||||
const screenfullChange = () => {
|
||||
player.aspectRatioReset();
|
||||
art.emit('fullscreen', screenfull.isFullscreen);
|
||||
};
|
||||
|
||||
const screenfullError = () => {
|
||||
notice.show('Your browser does not seem to support full screen functionality.');
|
||||
};
|
||||
|
||||
screenfull.on('change', screenfullChange);
|
||||
screenfull.on('error', screenfullError);
|
||||
destroyEvents.push(() => {
|
||||
screenfull.off('change', screenfullChange);
|
||||
screenfull.off('error', screenfullError);
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'fullscreenState', {
|
||||
get: () => screenfull.isFullscreen
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'fullscreenEnabled', {
|
||||
value: () => {
|
||||
if (player.fullscreenWebState) {
|
||||
player.fullscreenWebExit();
|
||||
}
|
||||
$player.classList.add('artplayer-fullscreen');
|
||||
screenfull.request($player);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'fullscreenExit', {
|
||||
value: () => {
|
||||
if (player.fullscreenWebState) {
|
||||
player.fullscreenWebExit();
|
||||
}
|
||||
$player.classList.remove('artplayer-fullscreen');
|
||||
screenfull.exit();
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'fullscreenToggle', {
|
||||
value: () => {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isFullscreen) {
|
||||
player.fullscreenExit();
|
||||
} else {
|
||||
player.fullscreenEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
export default function fullscreenWebMix(art, player) {
|
||||
const { refs: { $player } } = art;
|
||||
|
||||
Object.defineProperty(player, 'fullscreenWebState', {
|
||||
get: () => $player.classList.contains('artplayer-web-fullscreen')
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'fullscreenWebEnabled', {
|
||||
value: () => {
|
||||
if (player.fullscreenState) {
|
||||
player.fullscreenExit();
|
||||
}
|
||||
$player.classList.add('artplayer-web-fullscreen');
|
||||
player.aspectRatioReset();
|
||||
art.emit('fullscreenWeb', true);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'fullscreenWebExit', {
|
||||
value: () => {
|
||||
if (player.fullscreenState) {
|
||||
player.fullscreenExit();
|
||||
}
|
||||
$player.classList.remove('artplayer-web-fullscreen');
|
||||
player.aspectRatioReset();
|
||||
art.emit('fullscreenWeb', false);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'fullscreenWebToggle', {
|
||||
value: () => {
|
||||
if (player.fullscreenWebState) {
|
||||
player.exit();
|
||||
} else {
|
||||
player.enabled();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -10,6 +10,9 @@ import durationMix from './durationMix';
|
||||
import switchMix from './switchMix';
|
||||
import playbackRateMix from './playbackRateMix';
|
||||
import aspectRatioMix from './aspectRatioMix';
|
||||
import screenshotMix from './screenshotMix';
|
||||
import fullscreenMix from './fullscreenMix';
|
||||
import fullscreenWebMix from './fullscreenWebMix';
|
||||
|
||||
export default class Player {
|
||||
constructor(art) {
|
||||
@@ -28,5 +31,8 @@ export default class Player {
|
||||
switchMix(art, this);
|
||||
playbackRateMix(art, this);
|
||||
aspectRatioMix(art, this);
|
||||
screenshotMix(art, this);
|
||||
fullscreenMix(art, this);
|
||||
fullscreenWebMix(art, this);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
export default function pauseMin(art, player) {
|
||||
const { refs: { $video }, i18n, notice } = art;
|
||||
|
||||
Object.defineProperty(player, 'pause', {
|
||||
value: () => {
|
||||
const { refs: { $video }, i18n, notice } = art;
|
||||
$video.pause();
|
||||
notice.show(i18n.get('Pause'));
|
||||
art.emit('pause', $video);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
export default function playMix(art, player) {
|
||||
const { refs: { $video }, i18n, notice } = art;
|
||||
|
||||
Object.defineProperty(player, 'play', {
|
||||
value: () => {
|
||||
const { refs: { $video }, i18n, notice } = art;
|
||||
const promise = $video.play();
|
||||
if (promise !== undefined) {
|
||||
promise.then().catch(err => {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { clamp, sublings } from '../utils';
|
||||
|
||||
export default function playbackRateMix(art, player) {
|
||||
const { refs: { $video, $player }, i18n, notice, contextmenu } = art;
|
||||
|
||||
Object.defineProperty(player, 'playbackRate', {
|
||||
value: rate => {
|
||||
const { refs: { $video, $player }, i18n, notice } = art;
|
||||
const newRate = clamp(rate, 0.1, 10);
|
||||
$video.playbackRate = newRate;
|
||||
$player.dataset.playbackRate = newRate;
|
||||
@@ -12,20 +13,18 @@ export default function playbackRateMix(art, player) {
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'removePlaybackRate', {
|
||||
Object.defineProperty(player, 'playbackRateRemove', {
|
||||
value: () => {
|
||||
const { contextmenu: { $playbackRate } } = art;
|
||||
if ($playbackRate) {
|
||||
const $normal = $playbackRate.querySelector('.normal');
|
||||
if (contextmenu.$playbackRate) {
|
||||
const $normal = contextmenu.$playbackRate.querySelector('.normal');
|
||||
sublings($normal).forEach(item => item.classList.remove('current'));
|
||||
$normal.classList.add('current');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(player, 'resetPlaybackRate', {
|
||||
Object.defineProperty(player, 'playbackRateReset', {
|
||||
value: () => {
|
||||
const { refs: { $player } } = art;
|
||||
const { playbackRate } = $player.dataset;
|
||||
if (playbackRate) {
|
||||
player.playbackRate(Number(playbackRate));
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { setStyle, secondToTime } from '../utils';
|
||||
|
||||
export default function screenshotMix(art, player) {
|
||||
const { notice } = art;
|
||||
|
||||
function captureFrame() {
|
||||
const { $video } = art.refs;
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = $video.videoWidth;
|
||||
canvas.height = $video.videoHeight;
|
||||
canvas.getContext('2d').drawImage($video, 0, 0);
|
||||
const dataUri = canvas.toDataURL('image/png');
|
||||
const elink = document.createElement('a');
|
||||
setStyle(elink, 'display', 'none');
|
||||
elink.href = dataUri;
|
||||
elink.download = `ArtPlayer_${secondToTime($video.currentTime)}.png`;
|
||||
document.body.appendChild(elink);
|
||||
elink.click();
|
||||
document.body.removeChild(elink);
|
||||
}
|
||||
|
||||
Object.defineProperty(player, 'screenshot', {
|
||||
value: () => {
|
||||
try {
|
||||
captureFrame();
|
||||
art.emit('screenshot');
|
||||
} catch (error) {
|
||||
notice.show(error);
|
||||
console.warn(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import { secondToTime } from '../utils';
|
||||
|
||||
export default function seekMix(art, player) {
|
||||
const { refs: { $video }, notice } = art;
|
||||
|
||||
Object.defineProperty(player, 'seek', {
|
||||
value: time => {
|
||||
const { refs: { $video }, notice } = art;
|
||||
let newTime = Math.max(time, 0);
|
||||
if ($video.duration) {
|
||||
newTime = Math.min(newTime, $video.duration);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
export default function switchMix(art, player) {
|
||||
const { refs: { $video }, i18n, notice, isPlaying, option } = art;
|
||||
|
||||
Object.defineProperty(player, 'switch', {
|
||||
value: (url, name = 'Unknown') => {
|
||||
const { refs: { $video }, i18n, notice, isPlaying, option } = art;
|
||||
const currentTime = player.currentTime();
|
||||
$video.src = url;
|
||||
option.url = url;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { clamp, setStorage } from '../utils';
|
||||
|
||||
export default function volumeMix(art, player) {
|
||||
const { refs: { $video }, i18n, notice } = art;
|
||||
|
||||
Object.defineProperty(player, 'volume', {
|
||||
value: percentage => {
|
||||
const { refs: { $video }, i18n, notice } = art;
|
||||
if (percentage !== undefined) {
|
||||
$video.volume = clamp(percentage, 0, 1);
|
||||
notice.show(`${i18n.get('Volume')}: ${parseInt($video.volume * 100)}`);
|
||||
|
||||
Reference in new issue
Block a user