mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-19 19:51:20 -08:00
优化手机端UI
This commit is contained in:
1 parent
19a894fcb6
commit
beea013daf
16 files changed
+249
-129
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { errorHandle, addClass } from '../utils';
|
||||
import { errorHandle, addClass, debounce, removeClass } from '../utils';
|
||||
import Component from '../utils/component';
|
||||
import fullscreen from './fullscreen';
|
||||
import fullscreenWeb from './fullscreenWeb';
|
||||
@@ -19,7 +19,21 @@ export default class Control extends Component {
|
||||
|
||||
this.name = 'control';
|
||||
|
||||
const { option } = art;
|
||||
const {
|
||||
option,
|
||||
player,
|
||||
template: { $player },
|
||||
} = art;
|
||||
|
||||
this.delayHide = debounce(() => {
|
||||
if (player.playing && this.show) {
|
||||
addClass($player, 'art-hide-cursor');
|
||||
removeClass($player, 'art-hover');
|
||||
this.show = false;
|
||||
}
|
||||
}, 3000);
|
||||
|
||||
this.cancelDelayHide = this.delayHide.clearTimeout;
|
||||
|
||||
art.on('ready', () => {
|
||||
this.add(
|
||||
@@ -130,7 +144,7 @@ export default class Control extends Component {
|
||||
}),
|
||||
);
|
||||
|
||||
option.controls.forEach(item => {
|
||||
option.controls.forEach((item) => {
|
||||
this.add(item);
|
||||
});
|
||||
});
|
||||
@@ -158,7 +172,7 @@ export default class Control extends Component {
|
||||
break;
|
||||
}
|
||||
|
||||
super.add(option, $ref => {
|
||||
super.add(option, ($ref) => {
|
||||
if (
|
||||
!option.disable &&
|
||||
option.position !== 'top' &&
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { append, clamp, tooltip, setStyle } from '../utils';
|
||||
|
||||
export default function volume(option) {
|
||||
return art => ({
|
||||
return (art) => ({
|
||||
...option,
|
||||
mounted: $control => {
|
||||
mounted: ($control) => {
|
||||
const {
|
||||
events: { proxy },
|
||||
icons,
|
||||
@@ -21,6 +21,10 @@ export default function volume(option) {
|
||||
tooltip($volume, i18n.get('Mute'));
|
||||
setStyle($volumeClose, 'display', 'none');
|
||||
|
||||
if (art.isMobile) {
|
||||
setStyle($volumePanel, 'display', 'none');
|
||||
}
|
||||
|
||||
function volumeChangeFromEvent(event) {
|
||||
const { left: panelLeft } = $volumePanel.getBoundingClientRect();
|
||||
const percentage =
|
||||
@@ -55,7 +59,7 @@ export default function volume(option) {
|
||||
player.muted = false;
|
||||
});
|
||||
|
||||
proxy($volumePanel, 'click', event => {
|
||||
proxy($volumePanel, 'click', (event) => {
|
||||
player.muted = false;
|
||||
player.volume = volumeChangeFromEvent(event);
|
||||
});
|
||||
@@ -64,7 +68,7 @@ export default function volume(option) {
|
||||
isDroging = true;
|
||||
});
|
||||
|
||||
proxy($control, 'mousemove', event => {
|
||||
proxy($control, 'mousemove', (event) => {
|
||||
if (isDroging) {
|
||||
player.muted = false;
|
||||
player.volume = volumeChangeFromEvent(event);
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
export default function clickInit(art, events) {
|
||||
const { $player } = art.template;
|
||||
const {
|
||||
controls,
|
||||
template: { $player },
|
||||
} = art;
|
||||
|
||||
events.proxy(document, ['click', 'contextmenu'], (event) => {
|
||||
if (event.composedPath && event.composedPath().indexOf($player) > -1) {
|
||||
art.isFocus = true;
|
||||
art.emit('focus');
|
||||
} else if (art.isFocus) {
|
||||
} else {
|
||||
art.isFocus = false;
|
||||
art.emit('blur');
|
||||
}
|
||||
});
|
||||
|
||||
art.on('blur', () => {
|
||||
controls.delayHide();
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
import { addClass, removeClass } from '../utils';
|
||||
|
||||
export default function hoverInit(art, events) {
|
||||
const { $player } = art.template;
|
||||
const {
|
||||
controls,
|
||||
template: { $player },
|
||||
} = art;
|
||||
|
||||
events.hover(
|
||||
$player,
|
||||
() => {
|
||||
@@ -13,4 +17,8 @@ export default function hoverInit(art, events) {
|
||||
art.emit('hoverleave');
|
||||
},
|
||||
);
|
||||
|
||||
art.on('hoverleave', () => {
|
||||
controls.delayHide();
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { debounce, addClass, removeClass } from '../utils';
|
||||
import { removeClass } from '../utils';
|
||||
|
||||
export default function mousemoveInitInit(art, events) {
|
||||
const {
|
||||
@@ -7,25 +7,16 @@ export default function mousemoveInitInit(art, events) {
|
||||
controls,
|
||||
} = art;
|
||||
|
||||
const autoHide = debounce(() => {
|
||||
addClass($player, 'art-hide-cursor');
|
||||
removeClass($player, 'art-hover');
|
||||
controls.show = false;
|
||||
}, 3000);
|
||||
|
||||
art.on('hoverleave', () => {
|
||||
if (player.playing) {
|
||||
autoHide();
|
||||
}
|
||||
events.proxy($player, 'mousemove', (event) => {
|
||||
art.emit('mousemove', event);
|
||||
});
|
||||
|
||||
events.proxy($player, 'mousemove', event => {
|
||||
autoHide.clearTimeout();
|
||||
art.on('mousemove', (event) => {
|
||||
controls.cancelDelayHide();
|
||||
removeClass($player, 'art-hide-cursor');
|
||||
controls.show = true;
|
||||
if (!player.pip && player.playing && event.target === $video) {
|
||||
autoHide();
|
||||
if (!player.pip && event.target === $video) {
|
||||
controls.delayHide();
|
||||
}
|
||||
art.emit('mousemove');
|
||||
});
|
||||
}
|
||||
@@ -32,6 +32,8 @@ class Artplayer extends Emitter {
|
||||
this.option = validator(utils.mergeDeep(Artplayer.option, option), scheme);
|
||||
this.isFocus = false;
|
||||
this.isDestroy = false;
|
||||
this.ua = utils.userAgent;
|
||||
this.isMobile = utils.isMobile();
|
||||
this.whitelist = new Whitelist(this);
|
||||
this.template = new Template(this);
|
||||
this.events = new Events(this);
|
||||
|
||||
@@ -10,6 +10,7 @@ export default function eventInit(art, player) {
|
||||
notice,
|
||||
} = art;
|
||||
|
||||
let isReady = false;
|
||||
let reconnectTime = 0;
|
||||
const maxReconnectTime = 5;
|
||||
|
||||
@@ -17,8 +18,8 @@ export default function eventInit(art, player) {
|
||||
player.toggle = true;
|
||||
});
|
||||
|
||||
config.events.forEach(eventName => {
|
||||
proxy($video, eventName, event => {
|
||||
config.events.forEach((eventName) => {
|
||||
proxy($video, eventName, (event) => {
|
||||
art.emit(`video:${event.type}`, event);
|
||||
});
|
||||
});
|
||||
@@ -33,9 +34,13 @@ export default function eventInit(art, player) {
|
||||
});
|
||||
|
||||
art.once('video:canplay', () => {
|
||||
art.loading.show = false;
|
||||
art.controls.show = true;
|
||||
art.mask.show = true;
|
||||
art.emit('ready');
|
||||
if (!isReady) {
|
||||
art.emit('ready');
|
||||
isReady = true;
|
||||
}
|
||||
});
|
||||
|
||||
// art.on('video:canplaythrough', () => {
|
||||
@@ -84,10 +89,19 @@ export default function eventInit(art, player) {
|
||||
|
||||
// });
|
||||
|
||||
art.on('video:loadedmetadata', () => {
|
||||
art.once('video:loadedmetadata', () => {
|
||||
if (option.autoSize) {
|
||||
player.autoSize = true;
|
||||
}
|
||||
if (art.isMobile) {
|
||||
art.loading.show = false;
|
||||
art.controls.show = true;
|
||||
art.mask.show = true;
|
||||
if (!isReady) {
|
||||
art.emit('ready');
|
||||
isReady = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
art.on('video:loadstart', () => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
bottom: 40px;
|
||||
bottom: 10px;
|
||||
width: 100%;
|
||||
padding: 0 20px;
|
||||
text-align: center;
|
||||
@@ -24,4 +24,10 @@
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&.art-control-show {
|
||||
.art-subtitle {
|
||||
bottom: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,11 @@ export default class Subtitle extends Component {
|
||||
this.name = 'subtitle';
|
||||
|
||||
const {
|
||||
events: { proxy },
|
||||
option: { subtitle },
|
||||
template: { $subtitle },
|
||||
} = art;
|
||||
|
||||
setStyles($subtitle, subtitle.style);
|
||||
proxy(this.textTrack, 'cuechange', this.update.bind(this));
|
||||
|
||||
if (subtitle.url) {
|
||||
this.init(subtitle.url);
|
||||
@@ -22,7 +20,7 @@ export default class Subtitle extends Component {
|
||||
}
|
||||
|
||||
get url() {
|
||||
return this.art.template.$track.src;
|
||||
return this.$track.src;
|
||||
}
|
||||
|
||||
get textTrack() {
|
||||
@@ -39,7 +37,7 @@ export default class Subtitle extends Component {
|
||||
if (this.activeCue) {
|
||||
$subtitle.innerHTML = this.activeCue.text
|
||||
.split(/\r?\n/)
|
||||
.map(item => `<p>${escape(item)}</p>`)
|
||||
.map((item) => `<p>${escape(item)}</p>`)
|
||||
.join('');
|
||||
this.art.emit('subtitle:update', this.activeCue.text);
|
||||
}
|
||||
@@ -47,7 +45,7 @@ export default class Subtitle extends Component {
|
||||
|
||||
switch(url, name, ext) {
|
||||
const { i18n, notice } = this.art;
|
||||
return this.init(url, ext).then(subUrl => {
|
||||
return this.init(url, ext).then((subUrl) => {
|
||||
if (name) {
|
||||
notice.show = `${i18n.get('Switch subtitle')}: ${name}`;
|
||||
}
|
||||
@@ -59,14 +57,24 @@ export default class Subtitle extends Component {
|
||||
init(url, ext) {
|
||||
const {
|
||||
notice,
|
||||
template: { $subtitle, $track },
|
||||
events: { proxy },
|
||||
template: { $subtitle, $video },
|
||||
} = this.art;
|
||||
|
||||
if (!this.$track) {
|
||||
const $track = document.createElement('track');
|
||||
$track.default = true;
|
||||
$track.kind = 'metadata';
|
||||
$video.appendChild($track);
|
||||
this.$track = $track;
|
||||
proxy(this.textTrack, 'cuechange', this.update.bind(this));
|
||||
}
|
||||
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
return response.text();
|
||||
})
|
||||
.then(text => {
|
||||
.then((text) => {
|
||||
this.art.emit('subtitle:load', url);
|
||||
switch (ext || getExt(url)) {
|
||||
case 'srt':
|
||||
@@ -79,14 +87,14 @@ export default class Subtitle extends Component {
|
||||
return url;
|
||||
}
|
||||
})
|
||||
.then(subUrl => {
|
||||
.then((subUrl) => {
|
||||
$subtitle.innerHTML = '';
|
||||
if (this.url === subUrl) return subUrl;
|
||||
URL.revokeObjectURL(this.url);
|
||||
$track.src = subUrl;
|
||||
this.$track.src = subUrl;
|
||||
return subUrl;
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
notice.show = err;
|
||||
this.art.emit('subtitle:err', err);
|
||||
throw err;
|
||||
|
||||
@@ -37,9 +37,7 @@ export default class Template {
|
||||
this.$container.innerHTML = `
|
||||
<div class="art-undercover"></div>
|
||||
<div class="art-video-player art-subtitle-show art-layer-show" style="--theme: ${theme}">
|
||||
<video class="art-video">
|
||||
<track default kind="metadata"></track>
|
||||
</video>
|
||||
<video class="art-video"></video>
|
||||
<div class="art-subtitle"></div>
|
||||
<div class="art-danmuku"></div>
|
||||
<div class="art-layers"></div>
|
||||
@@ -104,7 +102,6 @@ export default class Template {
|
||||
this.$undercover = this.query('.art-undercover');
|
||||
this.$player = this.query('.art-video-player');
|
||||
this.$video = this.query('.art-video');
|
||||
this.$track = this.query('.art-video track');
|
||||
this.$subtitle = this.query('.art-subtitle');
|
||||
this.$danmuku = this.query('.art-danmuku');
|
||||
this.$bottom = this.query('.art-bottom');
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
import { isMobile, userAgent } from './utils/compatibility';
|
||||
|
||||
export default class Whitelist {
|
||||
constructor(art) {
|
||||
const {
|
||||
constructor: { kindOf },
|
||||
option: { whitelist },
|
||||
} = art;
|
||||
this.ua = userAgent;
|
||||
this.isMobile = isMobile();
|
||||
this.state =
|
||||
!this.isMobile ||
|
||||
!art.isMobile ||
|
||||
whitelist.some((item) => {
|
||||
switch (kindOf(item)) {
|
||||
case 'string':
|
||||
return this.ua.indexOf(item) > -1;
|
||||
return item === '*' || art.ua.indexOf(item) > -1;
|
||||
case 'function':
|
||||
return item(this.ua);
|
||||
return item(art.ua);
|
||||
case 'regexp':
|
||||
return item.test(this.ua);
|
||||
return item.test(art.ua);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user