优化手机端UI

This commit is contained in:
Harvey committed 2020-05-15 10:28:38 +08:00
1 parent 19a894fcb6
commit beea013daf
16 files changed
+249 -129

No files matched your search

+18 -4
View File
@@ -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' &&
+8 -4
View File
@@ -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);
+10 -2
View File
@@ -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();
});
}
+9 -1
View File
@@ -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();
});
}
+7 -16
View File
@@ -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');
});
}
+2
View File
@@ -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);
+18 -4
View File
@@ -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', () => {
+7 -1
View File
@@ -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;
}
}
}
+19 -11
View File
@@ -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;
+1 -4
View File
@@ -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');
+4 -8
View File
@@ -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;
}