优化整体结构

This commit is contained in:
Harvey Zack committed 2019-04-30 13:06:24 +08:00
1 parent 9f9cb0e036
commit 487e865017
34 files changed
+505 -427

No files matched your search

@@ -13,6 +13,10 @@ export default class Contextmenu {
this.art.on('firstCanplay', () => {
this.init();
});
this.art.on('blur', () => {
this.hide();
});
}
init() {
@@ -1,5 +1,4 @@
import { append, tooltip, setStyle } from '../utils';
import icons from '../icons';
export default function fullscreen(controlOption) {
return art => ({
@@ -11,7 +10,7 @@ export default function fullscreen(controlOption) {
player,
} = art;
const $fullscreen = append($control, icons.fullscreen);
const $fullscreen = append($control, art.icons.fullscreen);
tooltip($fullscreen, i18n.get('Fullscreen'));
proxy($control, 'click', () => {
@@ -1,5 +1,4 @@
import { append, tooltip, setStyle } from '../utils';
import icons from '../icons';
export default function fullscreenWeb(controlOption) {
return art => ({
@@ -11,7 +10,7 @@ export default function fullscreenWeb(controlOption) {
player,
} = art;
const $fullscreenWeb = append($control, icons.fullscreenWeb);
const $fullscreenWeb = append($control, art.icons.fullscreenWeb);
tooltip($fullscreenWeb, i18n.get('Web fullscreen'));
proxy($control, 'click', () => {
+3 -3
View File
@@ -28,7 +28,7 @@ export default class Controls {
this.add(
progress({
name: 'progress',
disable: option.isLive,
disable: false,
position: 'top',
index: 10,
}),
@@ -37,7 +37,7 @@ export default class Controls {
this.add(
thumbnails({
name: 'thumbnails',
disable: !option.thumbnails.url || option.isLive,
disable: !option.thumbnails.url,
position: 'top',
index: 20,
}),
@@ -64,7 +64,7 @@ export default class Controls {
this.add(
time({
name: 'time',
disable: option.isLive,
disable: false,
position: 'left',
index: 30,
}),
+1 -2
View File
@@ -1,5 +1,4 @@
import { append, tooltip } from '../utils';
import icons from '../icons';
export default function pip(controlOption) {
return art => ({
@@ -10,7 +9,7 @@ export default function pip(controlOption) {
i18n,
player,
} = art;
const $pip = append($control, icons.pip);
const $pip = append($control, art.icons.pip);
tooltip($pip, i18n.get('Mini player'));
proxy($control, 'click', () => {
player.pipEnabled();
@@ -1,5 +1,4 @@
import { append, tooltip, setStyle } from '../utils';
import icons from '../icons';
export default function playAndPause(controlOption) {
return art => ({
@@ -11,8 +10,8 @@ export default function playAndPause(controlOption) {
i18n,
} = art;
const $play = append($control, icons.play);
const $pause = append($control, icons.pause);
const $play = append($control, art.icons.play);
const $pause = append($control, art.icons.pause);
tooltip($play, i18n.get('Play'));
tooltip($pause, i18n.get('Pause'));
@@ -1,5 +1,4 @@
import { append, tooltip } from '../utils';
import icons from '../icons';
export default function screenshot(controlOption) {
return art => ({
@@ -11,7 +10,7 @@ export default function screenshot(controlOption) {
player,
} = art;
const $screenshot = append($control, icons.screenshot);
const $screenshot = append($control, art.icons.screenshot);
tooltip($screenshot, i18n.get('Screenshot'));
proxy($screenshot, 'click', () => {
player.screenshot();
+1 -2
View File
@@ -1,5 +1,4 @@
import { append, tooltip, setStyle } from '../utils';
import icons from '../icons';
export default function setting(controlOption) {
return art => ({
@@ -11,7 +10,7 @@ export default function setting(controlOption) {
setting,
} = art;
const $setting = append($control, icons.setting);
const $setting = append($control, art.icons.setting);
tooltip($setting, i18n.get('Show setting'));
proxy($control, 'click', () => {
+1 -2
View File
@@ -1,5 +1,4 @@
import { append, tooltip, setStyle } from '../utils';
import icons from '../icons';
export default function subtitle(controlOption) {
return art => ({
@@ -11,7 +10,7 @@ export default function subtitle(controlOption) {
subtitle,
} = art;
const $subtitle = append($control, icons.subtitle);
const $subtitle = append($control, art.icons.subtitle);
tooltip($subtitle, i18n.get('Hide subtitle'));
proxy($control, 'click', () => {
+2 -3
View File
@@ -1,5 +1,4 @@
import { append, clamp, tooltip, setStyle, getStyle } from '../utils';
import icons from '../icons';
export default function volume(controlOption) {
return art => ({
@@ -12,8 +11,8 @@ export default function volume(controlOption) {
} = art;
let isDroging = false;
const $volume = append($control, icons.volume);
const $volumeClose = append($control, icons.volumeClose);
const $volume = append($control, art.icons.volume);
const $volumeClose = append($control, art.icons.volumeClose);
const $volumePanel = append($control, '<div class="art-volume-panel"></div>');
const $volumeHandle = append($volumePanel, '<div class="art-volume-slider-handle"></div>');
tooltip($volume, i18n.get('Mute'));
+2 -1
View File
@@ -5,9 +5,10 @@ export default function clickInit(art, events) {
events.proxy(document, ['click', 'contextmenu'], event => {
if (event.composedPath().indexOf($player) > -1) {
art.isFocus = true;
art.emit('focus');
} else {
art.isFocus = false;
art.contextmenu.hide();
art.emit('blur');
}
});
}
@@ -3,7 +3,6 @@ export default function doubleClickInit(art, events) {
template: { $video },
} = art;
events.proxy($video, 'dblclick', () => {
art.player.fullscreenToggle();
art.emit('dblclick');
});
}
-2
View File
@@ -2,7 +2,6 @@ import clickInit from './clickInit';
import hoverInit from './hoverInit';
import mousemoveInit from './mousemoveInit';
import resizeInit from './resizeInit';
// import doubleClickInit from './doubleClickInit';
export default class Events {
constructor(art) {
@@ -15,7 +14,6 @@ export default class Events {
hoverInit(art, this);
mousemoveInit(art, this);
resizeInit(art, this);
// doubleClickInit(art, this);
});
}
+42 -28
View File
@@ -1,6 +1,34 @@
export default class Hotkey {
constructor(art) {
this.art = art;
this.keys = {};
this.add(27, () => {
if (art.isFocus && art.player.fullscreenWebState) {
art.player.fullscreenWebExit();
}
});
this.add(32, () => {
art.player.toggle();
});
this.add(37, () => {
art.player.seek(art.player.currentTime - 10);
});
this.add(38, () => {
art.player.volume += 0.05;
});
this.add(39, () => {
art.player.seek(art.player.currentTime + 10);
});
this.add(40, () => {
art.player.volume -= 0.05;
});
if (this.art.option.hotkey) {
this.art.on('firstCanplay', () => {
this.init();
@@ -8,40 +36,26 @@ export default class Hotkey {
}
}
add(key, event) {
if (this.keys[key]) {
this.keys[key].push(event);
} else {
this.keys[key] = [event];
}
}
init() {
const {
player,
events: { proxy },
} = this.art;
const { proxy } = this.art.events;
proxy(window, 'keydown', event => {
if (this.art.isFocus) {
const tag = document.activeElement.tagName.toUpperCase();
const editable = document.activeElement.getAttribute('contenteditable');
if (tag !== 'INPUT' && tag !== 'TEXTAREA' && editable !== '' && editable !== 'true') {
this.art.emit('hotkey', event);
switch (event.keyCode) {
case 39:
event.preventDefault();
player.seek(player.currentTime + 10);
break;
case 37:
event.preventDefault();
player.seek(player.currentTime - 10);
break;
case 38:
event.preventDefault();
player.volume += 0.05;
break;
case 40:
event.preventDefault();
player.volume -= 0.05;
break;
case 32:
event.preventDefault();
player.toggle();
break;
default:
break;
const events = this.keys[event.keyCode];
if (events) {
event.preventDefault();
events.forEach(fn => fn());
this.art.emit('hotkey', event);
}
}
}
-90
View File
@@ -1,90 +0,0 @@
import { mergeDeep } from './utils';
let i18nMap = {
'zh-cn': {
'About author': '关于作者',
'Video info': '视频统计信息',
Close: '关闭',
'Video load failed': '视频加载失败',
Volume: '音量',
Play: '播放',
Pause: '暂停',
Rate: '速度',
Mute: '静音',
Flip: '视频翻转',
Horizontal: '水平',
Vertical: '垂直',
Reconnect: '重新连接',
'Hide subtitle': '隐藏字幕',
'Show subtitle': '显示字幕',
'Hide danmu': '隐藏弹幕',
'Show danmu': '显示弹幕',
'Show setting': '显示设置',
'Hide setting': '隐藏设置',
Screenshot: '截图',
'Play speed': '播放速度',
'Aspect ratio': '画面比例',
Default: '默认',
Normal: '正常',
'Switch video': '切换',
'Switch subtitle': '切换字幕',
Fullscreen: '全屏',
'Exit fullscreen': '退出全屏',
'Web fullscreen': '网页全屏',
'Exit web fullscreen': '退出网页全屏',
'Mini player': '迷你播放器',
},
'zh-tw': {
'About author': '關於作者',
'Video info': '影片統計訊息',
Close: '關閉',
'Video load failed': '影片載入失敗',
Volume: '音量',
Play: '播放',
Pause: '暫停',
Rate: '速度',
Mute: '靜音',
Flip: '影片翻轉',
Horizontal: '水平',
Vertical: '垂直',
Reconnect: '重新連接',
'Hide subtitle': '隱藏字幕',
'Show subtitle': '顯示字幕',
'Show setting': '顯示设置',
'Hide setting': '隱藏设置',
'Hide danmu': '隱藏彈幕',
'Show danmu': '顯示彈幕',
Screenshot: '截圖',
'Play speed': '播放速度',
'Aspect ratio': '畫面比例',
Default: '默認',
Normal: '正常',
'Switch video': '切換',
'Switch subtitle': '切換字幕',
Fullscreen: '全屏',
'Exit fullscreen': '退出全屏',
'Web fullscreen': '網頁全屏',
'Exit web fullscreen': '退出網頁全屏',
'Mini player': '迷你播放器',
},
};
export default class I18n {
constructor(art) {
this.art = art;
this.init();
}
init() {
this.language = i18nMap[this.art.option.lang.toLowerCase()] || {};
}
get(key) {
return this.language[key] || key;
}
update(value) {
i18nMap = mergeDeep(i18nMap, value);
this.init();
}
}
+27
View File
@@ -0,0 +1,27 @@
import { mergeDeep } from '../utils';
import zhCn from './zh-cn';
import zhTw from './zh-tw';
export default class I18n {
constructor(art) {
this.art = art;
this.languages = {
'zh-cn': zhCn,
'zh-tw': zhTw,
};
this.init();
}
init() {
this.language = this.languages[this.art.option.lang.toLowerCase()] || {};
}
get(key) {
return this.language[key] || key;
}
update(value) {
this.languages = mergeDeep(this.languages, value);
this.init();
}
}
+33
View File
@@ -0,0 +1,33 @@
export default {
'About author': '关于作者',
'Video info': '视频统计信息',
Close: '关闭',
'Video load failed': '视频加载失败',
Volume: '音量',
Play: '播放',
Pause: '暂停',
Rate: '速度',
Mute: '静音',
Flip: '视频翻转',
Horizontal: '水平',
Vertical: '垂直',
Reconnect: '重新连接',
'Hide subtitle': '隐藏字幕',
'Show subtitle': '显示字幕',
'Hide danmu': '隐藏弹幕',
'Show danmu': '显示弹幕',
'Show setting': '显示设置',
'Hide setting': '隐藏设置',
Screenshot: '截图',
'Play speed': '播放速度',
'Aspect ratio': '画面比例',
Default: '默认',
Normal: '正常',
'Switch video': '切换',
'Switch subtitle': '切换字幕',
Fullscreen: '全屏',
'Exit fullscreen': '退出全屏',
'Web fullscreen': '网页全屏',
'Exit web fullscreen': '退出网页全屏',
'Mini player': '迷你播放器',
};
+33
View File
@@ -0,0 +1,33 @@
export default {
'About author': '關於作者',
'Video info': '影片統計訊息',
Close: '關閉',
'Video load failed': '影片載入失敗',
Volume: '音量',
Play: '播放',
Pause: '暫停',
Rate: '速度',
Mute: '靜音',
Flip: '影片翻轉',
Horizontal: '水平',
Vertical: '垂直',
Reconnect: '重新連接',
'Hide subtitle': '隱藏字幕',
'Show subtitle': '顯示字幕',
'Show setting': '顯示设置',
'Hide setting': '隱藏设置',
'Hide danmu': '隱藏彈幕',
'Show danmu': '顯示彈幕',
Screenshot: '截圖',
'Play speed': '播放速度',
'Aspect ratio': '畫面比例',
Default: '默認',
Normal: '正常',
'Switch video': '切換',
'Switch subtitle': '切換字幕',
Fullscreen: '全屏',
'Exit fullscreen': '退出全屏',
'Web fullscreen': '網頁全屏',
'Exit web fullscreen': '退出網頁全屏',
'Mini player': '迷你播放器',
};
+32 -28
View File
@@ -1,3 +1,4 @@
import { errorHandle } from '../utils';
import loading from './loading.svg';
import playBig from './play-big.svg';
import play from './play.svg';
@@ -13,32 +14,35 @@ import pip from './pip.svg';
import prev from './prev.svg';
import next from './next.svg';
const icons = {};
const svgs = {
loading,
playBig,
play,
pause,
volume,
volumeClose,
subtitle,
screenshot,
setting,
fullscreen,
fullscreenWeb,
pip,
prev,
next,
};
export default class Icons {
constructor(art) {
const icons = Object.assign(
{
loading,
playBig,
play,
pause,
volume,
volumeClose,
subtitle,
screenshot,
setting,
fullscreen,
fullscreenWeb,
pip,
prev,
next,
},
art.option.icons,
);
Object.keys(svgs).forEach(key => {
Object.defineProperty(icons, key, {
get() {
const tmp = document.createElement('div');
tmp.innerHTML = `<i class="art-icon art-icon-${key}">${svgs[key]}</i>`;
return tmp.childNodes[0];
},
});
});
export default icons;
Object.keys(icons).forEach(key => {
errorHandle(typeof icons[key] === 'string', 'Custom icon values ​​only support string types.');
const icon = document.createElement('i');
icon.classList.add('art-icon');
icon.classList.add(`art-icon-${key}`);
icon.innerHTML = icons[key];
this[key] = icon;
});
}
}
+6
View File
@@ -19,6 +19,7 @@ import Layers from './layers';
import Loading from './loading';
import Notice from './notice';
import Mask from './mask';
import Icons from './icons';
import Setting from './setting';
import Storage from './storage';
import Plugins from './plugins';
@@ -62,6 +63,10 @@ class Artplayer extends Emitter {
return validator;
}
static get kindOf() {
return validator.kindOf;
}
static get DEFAULTS() {
return {
container: '#artplayer',
@@ -121,6 +126,7 @@ class Artplayer extends Emitter {
this.isFocus = false;
this.isDestroy = false;
this.storage = new Storage(this);
this.icons = new Icons(this);
this.i18n = new I18n(this);
this.notice = new Notice(this);
this.events = new Events(this);
+1 -1
View File
@@ -14,8 +14,8 @@ export default class Layers {
}
add(item, callback) {
const { $layers } = this.art.template;
this.id += 1;
const { $layers } = this.art.template;
return component(this.art, this, $layers, item, callback, 'layer');
}
+2 -7
View File
@@ -1,15 +1,10 @@
import icons from './icons';
import { append, setStyle } from './utils';
export default class Loading {
constructor(art) {
this.art = art;
const {
option,
template: { $loading },
} = art;
append($loading, option.icons.loading || icons.loading);
const { $loading } = art.template;
append($loading, art.icons.loading);
}
hide() {
+2 -7
View File
@@ -1,16 +1,11 @@
import icons from './icons';
import { append, setStyle } from './utils';
export default class Mask {
constructor(art) {
this.art = art;
const {
option,
template: { $mask },
} = art;
const { $mask } = art.template;
const $playBig = append($mask, '<div class="art-playBig"></div>');
append($playBig, option.icons.playBig || icons.playBig);
append($playBig, art.icons.playBig);
}
show() {
@@ -1,8 +1,14 @@
import { clamp, errorHandle } from '../utils';
export default function currentTimeMix(art, player) {
Object.defineProperty(player, 'currentTime', {
get: () => art.template.$video.currentTime || 0,
set: currentTime => {
art.template.$video.currentTime = currentTime;
errorHandle(
player.duration,
'Cannot set current time, the video seems to be not ready for mate information.',
);
art.template.$video.currentTime = clamp(currentTime, 0, player.duration);
},
});
}
+3
View File
@@ -19,6 +19,7 @@ import loadedMix from './loadedMix';
import playedMix from './playedMix';
import playingMix from './playingMix';
import autoSizeMix from './autoSizeMix';
import rectMix from './rectMix';
import flipMix from './flipMix';
export default class Player {
@@ -44,6 +45,8 @@ export default class Player {
playedMix(art, this);
playingMix(art, this);
autoSizeMix(art, this);
rectMix(art, this);
flipMix(art, this);
}
}
+15
View File
@@ -0,0 +1,15 @@
export default function rectMix(art, player) {
Object.defineProperty(player, 'rect', {
get: () => {
return art.template.$player.getBoundingClientRect();
},
});
['bottom', 'height', 'left', 'right', 'top', 'width', 'x', 'y'].forEach(key => {
Object.defineProperty(player, key, {
get: () => {
return player.rect[key];
},
});
});
}
+3 -7
View File
@@ -5,13 +5,9 @@ export default function seekMix(art, player) {
Object.defineProperty(player, 'seek', {
value: time => {
let newTime = Math.max(time, 0);
if (player.duration) {
newTime = Math.min(newTime, player.duration);
}
player.currentTime = newTime;
notice.show(`${secondToTime(newTime)} / ${secondToTime(player.duration)}`);
art.emit('seek', newTime);
player.currentTime = time;
notice.show(`${secondToTime(time)} / ${secondToTime(player.duration)}`);
art.emit('seek', time);
},
});
}
+5 -7
View File
@@ -11,14 +11,12 @@ export default function volumeMix(art, player) {
Object.defineProperty(player, 'volume', {
get: () => $video.volume || 0,
set: percentage => {
if (percentage !== undefined) {
$video.volume = clamp(percentage, 0, 1);
notice.show(`${i18n.get('Volume')}: ${parseInt($video.volume * 100, 10)}`);
if ($video.volume !== 0) {
storage.set('volume', $video.volume);
}
art.emit('volumeChange', $video.volume);
$video.volume = clamp(percentage, 0, 1);
notice.show(`${i18n.get('Volume')}: ${parseInt($video.volume * 100, 10)}`);
if ($video.volume !== 0) {
storage.set('volume', $video.volume);
}
art.emit('volumeChange', $video.volume);
},
});
+5 -1
View File
@@ -11,6 +11,10 @@ export default class Setting {
this.art.on('firstCanplay', () => {
this.init();
});
this.art.on('blur', () => {
this.hide();
});
}
}
@@ -36,8 +40,8 @@ export default class Setting {
}
add(item, callback) {
const { $settingBody } = this.art.template;
this.id += 1;
const { $settingBody } = this.art.template;
return component(this.art, this, $settingBody, item, callback, 'setting');
}
+7 -3
View File
@@ -1,7 +1,7 @@
export default class Storage {
constructor(art) {
this.art = art;
this.storageName = 'artplayer_settings';
this.name = 'artplayer_settings';
this.init();
}
@@ -14,7 +14,7 @@ export default class Storage {
}
get(key) {
const storage = JSON.parse(localStorage.getItem(this.storageName)) || {};
const storage = JSON.parse(window.localStorage.getItem(this.name)) || {};
return key ? storage[key] : {};
}
@@ -22,6 +22,10 @@ export default class Storage {
const storage = Object.assign({}, this.get(), {
[key]: value,
});
localStorage.setItem(this.storageName, JSON.stringify(storage));
window.localStorage.setItem(this.name, JSON.stringify(storage));
}
clean() {
window.localStorage.removeItem(this.name);
}
}
+1
View File
@@ -6,6 +6,7 @@ export default class Template {
this.$container = art.option.container;
} else {
this.$container = document.querySelector(art.option.container);
errorHandle(this.$container, `No container element found by ${art.option.container}`);
}
if (art.constructor.instances.some(art => art.template.$container === this.$container)) {
+2 -3
View File
@@ -1,14 +1,13 @@
import optionValidator from 'option-validator';
export default class Whitelist {
constructor(art) {
const { kindOf } = art.constructor;
const { whitelist } = art.option;
this.userAgent = window.navigator.userAgent;
this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(this.userAgent);
this.state =
!this.isMobile ||
whitelist.some(item => {
const type = optionValidator.kindOf(item);
const type = kindOf(item);
let result = false;
switch (type) {
case 'string':