mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-24 23:51:20 -08:00
build all
Refactor utility functions for improved readability and consistency - Updated compatibility.js to use consistent line endings and formatting. - Refactored component.js for better readability and structure, including consistent use of arrow functions and binding. - Simplified dom.js functions with consistent formatting and improved readability. - Enhanced emitter.js with consistent formatting and arrow function usage. - Streamlined error.js for improved readability and consistency. - Refactored file.js to use consistent formatting and improved readability. - Improved format.js functions for better readability and consistency. - Updated index.js to maintain consistent export formatting. - Refactored property.js for improved readability and consistency. - Enhanced subtitle.js with consistent formatting and improved readability. - Refactored time.js for better readability and consistent formatting. fix: update lint script to target only source files for consistency Revert "fix: restore export statements for various plugins and update type definitions for better clarity" This reverts commit b5e969d81ec765cd8a34b06e6ef4f232ef25087f. fix: restore export statements for various plugins and update type definitions for better clarity Refactor type definitions to use interfaces instead of type aliases for better extensibility and clarity across i18n, icons, option, player, quality, setting, subtitle, template, and utils modules.
This commit is contained in:
1 parent
532dd67cfd
commit
35ad9883af
447 files changed
+18248
-17946
No files matched your search
@@ -1,38 +1,40 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function airplayMix(art) {
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
proxy,
|
||||
template: { $video },
|
||||
} = art;
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
proxy,
|
||||
template: { $video },
|
||||
} = art
|
||||
|
||||
let available = true;
|
||||
let available = true
|
||||
|
||||
if (window.WebKitPlaybackTargetAvailabilityEvent && $video.webkitShowPlaybackTargetPicker) {
|
||||
proxy($video, 'webkitplaybacktargetavailabilitychanged', (event) => {
|
||||
switch (event.availability) {
|
||||
case 'available':
|
||||
available = true;
|
||||
break;
|
||||
case 'not-available':
|
||||
available = false;
|
||||
break;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
available = false;
|
||||
}
|
||||
if (window.WebKitPlaybackTargetAvailabilityEvent && $video.webkitShowPlaybackTargetPicker) {
|
||||
proxy($video, 'webkitplaybacktargetavailabilitychanged', (event) => {
|
||||
switch (event.availability) {
|
||||
case 'available':
|
||||
available = true
|
||||
break
|
||||
case 'not-available':
|
||||
available = false
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
else {
|
||||
available = false
|
||||
}
|
||||
|
||||
def(art, 'airplay', {
|
||||
value() {
|
||||
if (available) {
|
||||
$video.webkitShowPlaybackTargetPicker();
|
||||
art.emit('airplay');
|
||||
} else {
|
||||
notice.show = i18n.get('AirPlay Not Available');
|
||||
}
|
||||
},
|
||||
});
|
||||
def(art, 'airplay', {
|
||||
value() {
|
||||
if (available) {
|
||||
$video.webkitShowPlaybackTargetPicker()
|
||||
art.emit('airplay')
|
||||
}
|
||||
else {
|
||||
notice.show = i18n.get('AirPlay Not Available')
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,44 +1,47 @@
|
||||
import { setStyle, def } from '../utils';
|
||||
import { def, setStyle } from '../utils'
|
||||
|
||||
export default function aspectRatioMix(art) {
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
template: { $video, $player },
|
||||
} = art;
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
template: { $video, $player },
|
||||
} = art
|
||||
|
||||
def(art, 'aspectRatio', {
|
||||
get() {
|
||||
return $player.dataset.aspectRatio || 'default';
|
||||
},
|
||||
set(ratio) {
|
||||
if (!ratio) ratio = 'default';
|
||||
if (ratio === 'default') {
|
||||
setStyle($video, 'width', null);
|
||||
setStyle($video, 'height', null);
|
||||
setStyle($video, 'margin', null);
|
||||
delete $player.dataset.aspectRatio;
|
||||
} else {
|
||||
const ratioArray = ratio.split(':').map(Number);
|
||||
const { clientWidth, clientHeight } = $player;
|
||||
const playerRatio = clientWidth / clientHeight;
|
||||
const setupRatio = ratioArray[0] / ratioArray[1];
|
||||
def(art, 'aspectRatio', {
|
||||
get() {
|
||||
return $player.dataset.aspectRatio || 'default'
|
||||
},
|
||||
set(ratio) {
|
||||
if (!ratio)
|
||||
ratio = 'default'
|
||||
if (ratio === 'default') {
|
||||
setStyle($video, 'width', null)
|
||||
setStyle($video, 'height', null)
|
||||
setStyle($video, 'margin', null)
|
||||
delete $player.dataset.aspectRatio
|
||||
}
|
||||
else {
|
||||
const ratioArray = ratio.split(':').map(Number)
|
||||
const { clientWidth, clientHeight } = $player
|
||||
const playerRatio = clientWidth / clientHeight
|
||||
const setupRatio = ratioArray[0] / ratioArray[1]
|
||||
|
||||
if (playerRatio > setupRatio) {
|
||||
setStyle($video, 'width', `${setupRatio * clientHeight}px`);
|
||||
setStyle($video, 'height', '100%');
|
||||
setStyle($video, 'margin', '0 auto');
|
||||
} else {
|
||||
setStyle($video, 'width', '100%');
|
||||
setStyle($video, 'height', `${clientWidth / setupRatio}px`);
|
||||
setStyle($video, 'margin', 'auto 0');
|
||||
}
|
||||
if (playerRatio > setupRatio) {
|
||||
setStyle($video, 'width', `${setupRatio * clientHeight}px`)
|
||||
setStyle($video, 'height', '100%')
|
||||
setStyle($video, 'margin', '0 auto')
|
||||
}
|
||||
else {
|
||||
setStyle($video, 'width', '100%')
|
||||
setStyle($video, 'height', `${clientWidth / setupRatio}px`)
|
||||
setStyle($video, 'margin', 'auto 0')
|
||||
}
|
||||
|
||||
$player.dataset.aspectRatio = ratio;
|
||||
}
|
||||
$player.dataset.aspectRatio = ratio
|
||||
}
|
||||
|
||||
notice.show = `${i18n.get('Aspect Ratio')}: ${ratio === 'default' ? i18n.get('Default') : ratio}`;
|
||||
art.emit('aspectRatio', ratio);
|
||||
},
|
||||
});
|
||||
notice.show = `${i18n.get('Aspect Ratio')}: ${ratio === 'default' ? i18n.get('Default') : ratio}`
|
||||
art.emit('aspectRatio', ratio)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function attrMix(art) {
|
||||
const {
|
||||
template: { $video },
|
||||
} = art;
|
||||
const {
|
||||
template: { $video },
|
||||
} = art
|
||||
|
||||
def(art, 'attr', {
|
||||
value(key, value) {
|
||||
if (value === undefined) return $video[key];
|
||||
$video[key] = value;
|
||||
},
|
||||
});
|
||||
def(art, 'attr', {
|
||||
value(key, value) {
|
||||
if (value === undefined)
|
||||
return $video[key]
|
||||
$video[key] = value
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
import { setStyle, def } from '../utils';
|
||||
import { def, setStyle } from '../utils'
|
||||
|
||||
export default function autoHeightMix(art) {
|
||||
const {
|
||||
template: { $container, $video },
|
||||
} = art;
|
||||
const {
|
||||
template: { $container, $video },
|
||||
} = art
|
||||
|
||||
def(art, 'autoHeight', {
|
||||
value() {
|
||||
const { clientWidth } = $container;
|
||||
const { videoHeight, videoWidth } = $video;
|
||||
const height = videoHeight * (clientWidth / videoWidth);
|
||||
setStyle($container, 'height', height + 'px');
|
||||
art.emit('autoHeight', height);
|
||||
},
|
||||
});
|
||||
def(art, 'autoHeight', {
|
||||
value() {
|
||||
const { clientWidth } = $container
|
||||
const { videoHeight, videoWidth } = $video
|
||||
const height = videoHeight * (clientWidth / videoWidth)
|
||||
setStyle($container, 'height', `${height}px`)
|
||||
art.emit('autoHeight', height)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,27 +1,28 @@
|
||||
import { setStyle, def, getRect } from '../utils';
|
||||
import { def, getRect, setStyle } from '../utils'
|
||||
|
||||
export default function autoSizeMix(art) {
|
||||
const { $container, $player, $video } = art.template;
|
||||
const { $container, $player, $video } = art.template
|
||||
|
||||
def(art, 'autoSize', {
|
||||
value() {
|
||||
const { videoWidth, videoHeight } = $video;
|
||||
const { width, height } = getRect($container);
|
||||
const videoRatio = videoWidth / videoHeight;
|
||||
const containerRatio = width / height;
|
||||
if (containerRatio > videoRatio) {
|
||||
const percentage = ((height * videoRatio) / width) * 100;
|
||||
setStyle($player, 'width', `${percentage}%`);
|
||||
setStyle($player, 'height', '100%');
|
||||
} else {
|
||||
const percentage = (width / videoRatio / height) * 100;
|
||||
setStyle($player, 'width', '100%');
|
||||
setStyle($player, 'height', `${percentage}%`);
|
||||
}
|
||||
art.emit('autoSize', {
|
||||
width: art.width,
|
||||
height: art.height,
|
||||
});
|
||||
},
|
||||
});
|
||||
def(art, 'autoSize', {
|
||||
value() {
|
||||
const { videoWidth, videoHeight } = $video
|
||||
const { width, height } = getRect($container)
|
||||
const videoRatio = videoWidth / videoHeight
|
||||
const containerRatio = width / height
|
||||
if (containerRatio > videoRatio) {
|
||||
const percentage = ((height * videoRatio) / width) * 100
|
||||
setStyle($player, 'width', `${percentage}%`)
|
||||
setStyle($player, 'height', '100%')
|
||||
}
|
||||
else {
|
||||
const percentage = (width / videoRatio / height) * 100
|
||||
setStyle($player, 'width', '100%')
|
||||
setStyle($player, 'height', `${percentage}%`)
|
||||
}
|
||||
art.emit('autoSize', {
|
||||
width: art.width,
|
||||
height: art.height,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function cssVarMix(art) {
|
||||
const { $player } = art.template;
|
||||
const { $player } = art.template
|
||||
|
||||
def(art, 'cssVar', {
|
||||
value(key, value) {
|
||||
if (value) {
|
||||
return $player.style.setProperty(key, value);
|
||||
} else {
|
||||
return getComputedStyle($player).getPropertyValue(key);
|
||||
}
|
||||
},
|
||||
});
|
||||
def(art, 'cssVar', {
|
||||
value(key, value) {
|
||||
if (value) {
|
||||
return $player.style.setProperty(key, value)
|
||||
}
|
||||
else {
|
||||
return getComputedStyle($player).getPropertyValue(key)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
import { clamp, def } from '../utils';
|
||||
import { clamp, def } from '../utils'
|
||||
|
||||
export default function currentTimeMix(art) {
|
||||
const { $video } = art.template;
|
||||
const { $video } = art.template
|
||||
|
||||
def(art, 'currentTime', {
|
||||
get: () => $video.currentTime || 0,
|
||||
set: (time) => {
|
||||
time = parseFloat(time);
|
||||
if (Number.isNaN(time)) return;
|
||||
$video.currentTime = clamp(time, 0, art.duration);
|
||||
},
|
||||
});
|
||||
def(art, 'currentTime', {
|
||||
get: () => $video.currentTime || 0,
|
||||
set: (time) => {
|
||||
time = Number.parseFloat(time)
|
||||
if (Number.isNaN(time))
|
||||
return
|
||||
$video.currentTime = clamp(time, 0, art.duration)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function durationMix(art) {
|
||||
def(art, 'duration', {
|
||||
get: () => {
|
||||
const { duration } = art.template.$video;
|
||||
if (duration === Infinity) return 0;
|
||||
return duration || 0;
|
||||
},
|
||||
});
|
||||
def(art, 'duration', {
|
||||
get: () => {
|
||||
const { duration } = art.template.$video
|
||||
if (duration === Infinity)
|
||||
return 0
|
||||
return duration || 0
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,153 +1,155 @@
|
||||
import config from '../config';
|
||||
import { sleep, addClass, setStyle, isMobile } from '../utils';
|
||||
import config from '../config'
|
||||
import { addClass, isMobile, setStyle, sleep } from '../utils'
|
||||
|
||||
export default function eventInit(art) {
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
option,
|
||||
constructor,
|
||||
proxy,
|
||||
template: { $player, $video, $poster },
|
||||
} = art;
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
option,
|
||||
constructor,
|
||||
proxy,
|
||||
template: { $player, $video, $poster },
|
||||
} = art
|
||||
|
||||
let reconnectTime = 0;
|
||||
let reconnectTime = 0
|
||||
|
||||
for (let index = 0; index < config.events.length; index++) {
|
||||
proxy($video, config.events[index], (event) => {
|
||||
art.emit(`video:${event.type}`, event);
|
||||
});
|
||||
for (let index = 0; index < config.events.length; index++) {
|
||||
proxy($video, config.events[index], (event) => {
|
||||
art.emit(`video:${event.type}`, event)
|
||||
})
|
||||
}
|
||||
|
||||
// art.on('video:abort', () => {
|
||||
|
||||
// });
|
||||
|
||||
art.on('video:canplay', () => {
|
||||
reconnectTime = 0
|
||||
art.loading.show = false
|
||||
})
|
||||
|
||||
art.once('video:canplay', () => {
|
||||
art.loading.show = false
|
||||
art.controls.show = true
|
||||
art.mask.show = true
|
||||
art.isReady = true
|
||||
art.emit('ready')
|
||||
})
|
||||
|
||||
// art.on('video:canplaythrough', () => {
|
||||
|
||||
// });
|
||||
|
||||
// art.on('video:durationchange', () => {
|
||||
|
||||
// });
|
||||
|
||||
// art.on('video:emptied', () => {
|
||||
|
||||
// });
|
||||
|
||||
art.on('video:ended', () => {
|
||||
if (option.loop) {
|
||||
art.seek = 0
|
||||
art.play()
|
||||
art.controls.show = false
|
||||
art.mask.show = false
|
||||
}
|
||||
else {
|
||||
art.controls.show = true
|
||||
art.mask.show = true
|
||||
}
|
||||
})
|
||||
|
||||
// art.on('video:abort', () => {
|
||||
art.on('video:error', async (error) => {
|
||||
if (reconnectTime < constructor.RECONNECT_TIME_MAX) {
|
||||
await sleep(constructor.RECONNECT_SLEEP_TIME)
|
||||
reconnectTime += 1
|
||||
art.url = option.url
|
||||
notice.show = `${i18n.get('Reconnect')}: ${reconnectTime}`
|
||||
art.emit('error', error, reconnectTime)
|
||||
}
|
||||
else {
|
||||
art.mask.show = true
|
||||
art.loading.show = false
|
||||
art.controls.show = true
|
||||
addClass($player, 'art-error')
|
||||
await sleep(constructor.RECONNECT_SLEEP_TIME)
|
||||
notice.show = i18n.get('Video Load Failed')
|
||||
}
|
||||
})
|
||||
|
||||
// });
|
||||
// art.on('video:loadeddata', () => {
|
||||
|
||||
art.on('video:canplay', () => {
|
||||
reconnectTime = 0;
|
||||
art.loading.show = false;
|
||||
});
|
||||
// });
|
||||
|
||||
art.once('video:canplay', () => {
|
||||
art.loading.show = false;
|
||||
art.controls.show = true;
|
||||
art.mask.show = true;
|
||||
art.isReady = true;
|
||||
art.emit('ready');
|
||||
});
|
||||
art.on('video:loadedmetadata', () => {
|
||||
art.emit('resize')
|
||||
if (isMobile) {
|
||||
art.loading.show = false
|
||||
art.controls.show = true
|
||||
art.mask.show = true
|
||||
}
|
||||
})
|
||||
|
||||
// art.on('video:canplaythrough', () => {
|
||||
art.on('video:loadstart', () => {
|
||||
art.loading.show = true
|
||||
art.mask.show = false
|
||||
art.controls.show = true
|
||||
})
|
||||
|
||||
// });
|
||||
art.on('video:pause', () => {
|
||||
art.controls.show = true
|
||||
art.mask.show = true
|
||||
})
|
||||
|
||||
// art.on('video:durationchange', () => {
|
||||
art.on('video:play', () => {
|
||||
art.mask.show = false
|
||||
setStyle($poster, 'display', 'none')
|
||||
})
|
||||
|
||||
// });
|
||||
art.on('video:playing', () => {
|
||||
art.mask.show = false
|
||||
})
|
||||
|
||||
// art.on('video:emptied', () => {
|
||||
art.on('video:progress', () => {
|
||||
if (art.playing) {
|
||||
art.loading.show = false
|
||||
}
|
||||
})
|
||||
|
||||
// });
|
||||
// art.on('video:ratechange', () => {
|
||||
|
||||
art.on('video:ended', () => {
|
||||
if (option.loop) {
|
||||
art.seek = 0;
|
||||
art.play();
|
||||
art.controls.show = false;
|
||||
art.mask.show = false;
|
||||
} else {
|
||||
art.controls.show = true;
|
||||
art.mask.show = true;
|
||||
}
|
||||
});
|
||||
// });
|
||||
|
||||
art.on('video:error', async (error) => {
|
||||
if (reconnectTime < constructor.RECONNECT_TIME_MAX) {
|
||||
await sleep(constructor.RECONNECT_SLEEP_TIME);
|
||||
reconnectTime += 1;
|
||||
art.url = option.url;
|
||||
notice.show = `${i18n.get('Reconnect')}: ${reconnectTime}`;
|
||||
art.emit('error', error, reconnectTime);
|
||||
} else {
|
||||
art.mask.show = true;
|
||||
art.loading.show = false;
|
||||
art.controls.show = true;
|
||||
addClass($player, 'art-error');
|
||||
await sleep(constructor.RECONNECT_SLEEP_TIME);
|
||||
notice.show = i18n.get('Video Load Failed');
|
||||
}
|
||||
});
|
||||
art.on('video:seeked', () => {
|
||||
art.loading.show = false
|
||||
art.mask.show = true
|
||||
})
|
||||
|
||||
// art.on('video:loadeddata', () => {
|
||||
art.on('video:seeking', () => {
|
||||
art.loading.show = true
|
||||
art.mask.show = false
|
||||
})
|
||||
|
||||
// });
|
||||
// art.on('video:stalled', () => {
|
||||
|
||||
art.on('video:loadedmetadata', () => {
|
||||
art.emit('resize');
|
||||
if (isMobile) {
|
||||
art.loading.show = false;
|
||||
art.controls.show = true;
|
||||
art.mask.show = true;
|
||||
}
|
||||
});
|
||||
// });
|
||||
|
||||
art.on('video:loadstart', () => {
|
||||
art.loading.show = true;
|
||||
art.mask.show = false;
|
||||
art.controls.show = true;
|
||||
});
|
||||
// art.on('video:suspend', () => {
|
||||
|
||||
art.on('video:pause', () => {
|
||||
art.controls.show = true;
|
||||
art.mask.show = true;
|
||||
});
|
||||
// });
|
||||
|
||||
art.on('video:play', () => {
|
||||
art.mask.show = false;
|
||||
setStyle($poster, 'display', 'none');
|
||||
});
|
||||
art.on('video:timeupdate', () => {
|
||||
art.mask.show = false
|
||||
})
|
||||
|
||||
art.on('video:playing', () => {
|
||||
art.mask.show = false;
|
||||
});
|
||||
// art.on('video:volumechange', () => {
|
||||
|
||||
art.on('video:progress', () => {
|
||||
if (art.playing) {
|
||||
art.loading.show = false;
|
||||
}
|
||||
});
|
||||
// });
|
||||
|
||||
// art.on('video:ratechange', () => {
|
||||
|
||||
// });
|
||||
|
||||
art.on('video:seeked', () => {
|
||||
art.loading.show = false;
|
||||
art.mask.show = true;
|
||||
});
|
||||
|
||||
art.on('video:seeking', () => {
|
||||
art.loading.show = true;
|
||||
art.mask.show = false;
|
||||
});
|
||||
|
||||
// art.on('video:stalled', () => {
|
||||
|
||||
// });
|
||||
|
||||
// art.on('video:suspend', () => {
|
||||
|
||||
// });
|
||||
|
||||
art.on('video:timeupdate', () => {
|
||||
art.mask.show = false;
|
||||
});
|
||||
|
||||
// art.on('video:volumechange', () => {
|
||||
|
||||
// });
|
||||
|
||||
art.on('video:waiting', () => {
|
||||
art.loading.show = true;
|
||||
art.mask.show = false;
|
||||
});
|
||||
art.on('video:waiting', () => {
|
||||
art.loading.show = true
|
||||
art.mask.show = false
|
||||
})
|
||||
}
|
||||
@@ -1,26 +1,28 @@
|
||||
import { def, capitalize } from '../utils';
|
||||
import { capitalize, def } from '../utils'
|
||||
|
||||
export default function flipMix(art) {
|
||||
const {
|
||||
template: { $player },
|
||||
i18n,
|
||||
notice,
|
||||
} = art;
|
||||
const {
|
||||
template: { $player },
|
||||
i18n,
|
||||
notice,
|
||||
} = art
|
||||
|
||||
def(art, 'flip', {
|
||||
get() {
|
||||
return $player.dataset.flip || 'normal';
|
||||
},
|
||||
set(flip) {
|
||||
if (!flip) flip = 'normal';
|
||||
if (flip === 'normal') {
|
||||
delete $player.dataset.flip;
|
||||
} else {
|
||||
$player.dataset.flip = flip;
|
||||
}
|
||||
def(art, 'flip', {
|
||||
get() {
|
||||
return $player.dataset.flip || 'normal'
|
||||
},
|
||||
set(flip) {
|
||||
if (!flip)
|
||||
flip = 'normal'
|
||||
if (flip === 'normal') {
|
||||
delete $player.dataset.flip
|
||||
}
|
||||
else {
|
||||
$player.dataset.flip = flip
|
||||
}
|
||||
|
||||
notice.show = `${i18n.get('Video Flip')}: ${i18n.get(capitalize(flip))}`;
|
||||
art.emit('flip', flip);
|
||||
},
|
||||
});
|
||||
notice.show = `${i18n.get('Video Flip')}: ${i18n.get(capitalize(flip))}`
|
||||
art.emit('flip', flip)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,83 +1,88 @@
|
||||
import screenfull from '../libs/screenfull';
|
||||
import { addClass, removeClass, def, get } from '../utils';
|
||||
import screenfull from '../libs/screenfull'
|
||||
import { addClass, def, get, removeClass } from '../utils'
|
||||
|
||||
export default function fullscreenMix(art) {
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
template: { $video, $player },
|
||||
} = art;
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
template: { $video, $player },
|
||||
} = art
|
||||
|
||||
const nativeScreenfull = (art) => {
|
||||
screenfull.on('change', () => {
|
||||
art.emit('fullscreen', screenfull.isFullscreen);
|
||||
const nativeScreenfull = (art) => {
|
||||
screenfull.on('change', () => {
|
||||
art.emit('fullscreen', screenfull.isFullscreen)
|
||||
|
||||
if (screenfull.isFullscreen) {
|
||||
art.state = 'fullscreen';
|
||||
addClass($player, 'art-fullscreen');
|
||||
} else {
|
||||
removeClass($player, 'art-fullscreen');
|
||||
}
|
||||
if (screenfull.isFullscreen) {
|
||||
art.state = 'fullscreen'
|
||||
addClass($player, 'art-fullscreen')
|
||||
}
|
||||
else {
|
||||
removeClass($player, 'art-fullscreen')
|
||||
}
|
||||
|
||||
art.emit('resize');
|
||||
});
|
||||
art.emit('resize')
|
||||
})
|
||||
|
||||
screenfull.on('error', (event) => {
|
||||
art.emit('fullscreenError', event);
|
||||
});
|
||||
screenfull.on('error', (event) => {
|
||||
art.emit('fullscreenError', event)
|
||||
})
|
||||
|
||||
def(art, 'fullscreen', {
|
||||
get() {
|
||||
return screenfull.isFullscreen;
|
||||
},
|
||||
async set(value) {
|
||||
if (value) {
|
||||
await screenfull.request($player);
|
||||
} else {
|
||||
await screenfull.exit();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const webkitScreenfull = (art) => {
|
||||
art.proxy(document, 'webkitfullscreenchange', () => {
|
||||
art.emit('fullscreen', art.fullscreen);
|
||||
art.emit('resize');
|
||||
});
|
||||
|
||||
def(art, 'fullscreen', {
|
||||
get() {
|
||||
return document.fullscreenElement === $video;
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
art.state = 'fullscreen';
|
||||
$video.webkitEnterFullscreen();
|
||||
} else {
|
||||
$video.webkitExitFullscreen();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
art.once('video:loadedmetadata', () => {
|
||||
if (screenfull.isEnabled) {
|
||||
nativeScreenfull(art);
|
||||
} else if ($video.webkitSupportsFullscreen) {
|
||||
webkitScreenfull(art);
|
||||
} else {
|
||||
def(art, 'fullscreen', {
|
||||
get() {
|
||||
return false;
|
||||
},
|
||||
set() {
|
||||
notice.show = i18n.get('Fullscreen Not Supported');
|
||||
},
|
||||
});
|
||||
def(art, 'fullscreen', {
|
||||
get() {
|
||||
return screenfull.isFullscreen
|
||||
},
|
||||
async set(value) {
|
||||
if (value) {
|
||||
await screenfull.request($player)
|
||||
}
|
||||
else {
|
||||
await screenfull.exit()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Asynchronous setting
|
||||
def(art, 'fullscreen', get(art, 'fullscreen'));
|
||||
});
|
||||
const webkitScreenfull = (art) => {
|
||||
art.proxy(document, 'webkitfullscreenchange', () => {
|
||||
art.emit('fullscreen', art.fullscreen)
|
||||
art.emit('resize')
|
||||
})
|
||||
|
||||
def(art, 'fullscreen', {
|
||||
get() {
|
||||
return document.fullscreenElement === $video
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
art.state = 'fullscreen'
|
||||
$video.webkitEnterFullscreen()
|
||||
}
|
||||
else {
|
||||
$video.webkitExitFullscreen()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
art.once('video:loadedmetadata', () => {
|
||||
if (screenfull.isEnabled) {
|
||||
nativeScreenfull(art)
|
||||
}
|
||||
else if ($video.webkitSupportsFullscreen) {
|
||||
webkitScreenfull(art)
|
||||
}
|
||||
else {
|
||||
def(art, 'fullscreen', {
|
||||
get() {
|
||||
return false
|
||||
},
|
||||
set() {
|
||||
notice.show = i18n.get('Fullscreen Not Supported')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Asynchronous setting
|
||||
def(art, 'fullscreen', get(art, 'fullscreen'))
|
||||
})
|
||||
}
|
||||
@@ -1,40 +1,41 @@
|
||||
import { addClass, removeClass, hasClass, def, append, setStyle } from '../utils';
|
||||
import { addClass, append, def, hasClass, removeClass, setStyle } from '../utils'
|
||||
|
||||
export default function fullscreenWebMix(art) {
|
||||
const {
|
||||
constructor,
|
||||
template: { $container, $player },
|
||||
} = art;
|
||||
const {
|
||||
constructor,
|
||||
template: { $container, $player },
|
||||
} = art
|
||||
|
||||
let cssText = '';
|
||||
def(art, 'fullscreenWeb', {
|
||||
get() {
|
||||
return hasClass($player, 'art-fullscreen-web');
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
cssText = $player.style.cssText;
|
||||
if (constructor.FULLSCREEN_WEB_IN_BODY) {
|
||||
append(document.body, $player);
|
||||
}
|
||||
art.state = 'fullscreenWeb';
|
||||
setStyle($player, 'width', '100%');
|
||||
setStyle($player, 'height', '100%');
|
||||
addClass($player, 'art-fullscreen-web');
|
||||
art.emit('fullscreenWeb', true);
|
||||
} else {
|
||||
if (constructor.FULLSCREEN_WEB_IN_BODY) {
|
||||
append($container, $player);
|
||||
}
|
||||
if (cssText) {
|
||||
$player.style.cssText = cssText;
|
||||
cssText = '';
|
||||
}
|
||||
removeClass($player, 'art-fullscreen-web');
|
||||
art.emit('fullscreenWeb', false);
|
||||
}
|
||||
let cssText = ''
|
||||
def(art, 'fullscreenWeb', {
|
||||
get() {
|
||||
return hasClass($player, 'art-fullscreen-web')
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
cssText = $player.style.cssText
|
||||
if (constructor.FULLSCREEN_WEB_IN_BODY) {
|
||||
append(document.body, $player)
|
||||
}
|
||||
art.state = 'fullscreenWeb'
|
||||
setStyle($player, 'width', '100%')
|
||||
setStyle($player, 'height', '100%')
|
||||
addClass($player, 'art-fullscreen-web')
|
||||
art.emit('fullscreenWeb', true)
|
||||
}
|
||||
else {
|
||||
if (constructor.FULLSCREEN_WEB_IN_BODY) {
|
||||
append($container, $player)
|
||||
}
|
||||
if (cssText) {
|
||||
$player.style.cssText = cssText
|
||||
cssText = ''
|
||||
}
|
||||
removeClass($player, 'art-fullscreen-web')
|
||||
art.emit('fullscreenWeb', false)
|
||||
}
|
||||
|
||||
art.emit('resize');
|
||||
},
|
||||
});
|
||||
art.emit('resize')
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,75 +1,75 @@
|
||||
import urlMix from './urlMix';
|
||||
import attrMix from './attrMix';
|
||||
import playMix from './playMix';
|
||||
import pauseMix from './pauseMix';
|
||||
import toggleMix from './toggleMix';
|
||||
import seekMix from './seekMix';
|
||||
import volumeMix from './volumeMix';
|
||||
import currentTimeMix from './currentTimeMix';
|
||||
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';
|
||||
import pipMix from './pipMix';
|
||||
import loadedMix from './loadedMix';
|
||||
import playedMix from './playedMix';
|
||||
import playingMix from './playingMix';
|
||||
import autoSizeMix from './autoSizeMix';
|
||||
import rectMix from './rectMix';
|
||||
import flipMix from './flipMix';
|
||||
import miniMix from './miniMix';
|
||||
import posterMix from './posterMix';
|
||||
import autoHeightMix from './autoHeightMix';
|
||||
import cssVarMix from './cssVarMix';
|
||||
import themeMix from './themeMix';
|
||||
import typeMix from './typeMix';
|
||||
import stateMix from './stateMix';
|
||||
import subtitleOffsetMix from './subtitleOffsetMix';
|
||||
import airplayMix from './airplayMix';
|
||||
import qualityMix from './qualityMix';
|
||||
import thumbnailsMix from './thumbnailsMix';
|
||||
import optionInit from './optionInit';
|
||||
import eventInit from './eventInit';
|
||||
import airplayMix from './airplayMix'
|
||||
import aspectRatioMix from './aspectRatioMix'
|
||||
import attrMix from './attrMix'
|
||||
import autoHeightMix from './autoHeightMix'
|
||||
import autoSizeMix from './autoSizeMix'
|
||||
import cssVarMix from './cssVarMix'
|
||||
import currentTimeMix from './currentTimeMix'
|
||||
import durationMix from './durationMix'
|
||||
import eventInit from './eventInit'
|
||||
import flipMix from './flipMix'
|
||||
import fullscreenMix from './fullscreenMix'
|
||||
import fullscreenWebMix from './fullscreenWebMix'
|
||||
import loadedMix from './loadedMix'
|
||||
import miniMix from './miniMix'
|
||||
import optionInit from './optionInit'
|
||||
import pauseMix from './pauseMix'
|
||||
import pipMix from './pipMix'
|
||||
import playbackRateMix from './playbackRateMix'
|
||||
import playedMix from './playedMix'
|
||||
import playingMix from './playingMix'
|
||||
import playMix from './playMix'
|
||||
import posterMix from './posterMix'
|
||||
import qualityMix from './qualityMix'
|
||||
import rectMix from './rectMix'
|
||||
import screenshotMix from './screenshotMix'
|
||||
import seekMix from './seekMix'
|
||||
import stateMix from './stateMix'
|
||||
import subtitleOffsetMix from './subtitleOffsetMix'
|
||||
import switchMix from './switchMix'
|
||||
import themeMix from './themeMix'
|
||||
import thumbnailsMix from './thumbnailsMix'
|
||||
import toggleMix from './toggleMix'
|
||||
import typeMix from './typeMix'
|
||||
import urlMix from './urlMix'
|
||||
import volumeMix from './volumeMix'
|
||||
|
||||
export default class Player {
|
||||
constructor(art) {
|
||||
urlMix(art);
|
||||
attrMix(art);
|
||||
playMix(art);
|
||||
pauseMix(art);
|
||||
toggleMix(art);
|
||||
seekMix(art);
|
||||
volumeMix(art);
|
||||
currentTimeMix(art);
|
||||
durationMix(art);
|
||||
switchMix(art);
|
||||
playbackRateMix(art);
|
||||
aspectRatioMix(art);
|
||||
screenshotMix(art);
|
||||
fullscreenMix(art);
|
||||
fullscreenWebMix(art);
|
||||
pipMix(art);
|
||||
loadedMix(art);
|
||||
playedMix(art);
|
||||
playingMix(art);
|
||||
autoSizeMix(art);
|
||||
rectMix(art);
|
||||
flipMix(art);
|
||||
miniMix(art);
|
||||
posterMix(art);
|
||||
autoHeightMix(art);
|
||||
cssVarMix(art);
|
||||
themeMix(art);
|
||||
typeMix(art);
|
||||
stateMix(art);
|
||||
subtitleOffsetMix(art);
|
||||
airplayMix(art);
|
||||
qualityMix(art);
|
||||
thumbnailsMix(art);
|
||||
eventInit(art);
|
||||
optionInit(art);
|
||||
}
|
||||
constructor(art) {
|
||||
urlMix(art)
|
||||
attrMix(art)
|
||||
playMix(art)
|
||||
pauseMix(art)
|
||||
toggleMix(art)
|
||||
seekMix(art)
|
||||
volumeMix(art)
|
||||
currentTimeMix(art)
|
||||
durationMix(art)
|
||||
switchMix(art)
|
||||
playbackRateMix(art)
|
||||
aspectRatioMix(art)
|
||||
screenshotMix(art)
|
||||
fullscreenMix(art)
|
||||
fullscreenWebMix(art)
|
||||
pipMix(art)
|
||||
loadedMix(art)
|
||||
playedMix(art)
|
||||
playingMix(art)
|
||||
autoSizeMix(art)
|
||||
rectMix(art)
|
||||
flipMix(art)
|
||||
miniMix(art)
|
||||
posterMix(art)
|
||||
autoHeightMix(art)
|
||||
cssVarMix(art)
|
||||
themeMix(art)
|
||||
typeMix(art)
|
||||
stateMix(art)
|
||||
subtitleOffsetMix(art)
|
||||
airplayMix(art)
|
||||
qualityMix(art)
|
||||
thumbnailsMix(art)
|
||||
eventInit(art)
|
||||
optionInit(art)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function loadedMix(art) {
|
||||
const { $video } = art.template;
|
||||
const { $video } = art.template
|
||||
|
||||
def(art, 'loaded', {
|
||||
get: () => art.loadedTime / $video.duration,
|
||||
});
|
||||
def(art, 'loaded', {
|
||||
get: () => art.loadedTime / $video.duration,
|
||||
})
|
||||
|
||||
def(art, 'loadedTime', {
|
||||
get: () => {
|
||||
return $video.buffered.length ? $video.buffered.end($video.buffered.length - 1) : 0;
|
||||
},
|
||||
});
|
||||
def(art, 'loadedTime', {
|
||||
get: () => {
|
||||
return $video.buffered.length ? $video.buffered.end($video.buffered.length - 1) : 0
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,130 +1,134 @@
|
||||
import { append, setStyle, addClass, removeClass, hasClass, def, isInViewport, createElement, getRect } from '../utils';
|
||||
import { addClass, append, createElement, def, getRect, hasClass, isInViewport, removeClass, setStyle } from '../utils'
|
||||
|
||||
export default function miniMix(art) {
|
||||
const {
|
||||
icons,
|
||||
proxy,
|
||||
storage,
|
||||
template: { $player, $video },
|
||||
} = art;
|
||||
const {
|
||||
icons,
|
||||
proxy,
|
||||
storage,
|
||||
template: { $player, $video },
|
||||
} = art
|
||||
|
||||
let isDragging = false;
|
||||
let lastPageX = 0;
|
||||
let lastPageY = 0;
|
||||
let isDragging = false
|
||||
let lastPageX = 0
|
||||
let lastPageY = 0
|
||||
|
||||
function hideMini() {
|
||||
const { $mini } = art.template;
|
||||
if ($mini) {
|
||||
removeClass($player, 'art-mini');
|
||||
setStyle($mini, 'display', 'none');
|
||||
$player.prepend($video);
|
||||
art.emit('mini', false);
|
||||
function hideMini() {
|
||||
const { $mini } = art.template
|
||||
if ($mini) {
|
||||
removeClass($player, 'art-mini')
|
||||
setStyle($mini, 'display', 'none')
|
||||
$player.prepend($video)
|
||||
art.emit('mini', false)
|
||||
}
|
||||
}
|
||||
|
||||
function initState($play, $pause) {
|
||||
if (art.playing) {
|
||||
setStyle($play, 'display', `none`)
|
||||
setStyle($pause, 'display', `flex`)
|
||||
}
|
||||
else {
|
||||
setStyle($play, 'display', `flex`)
|
||||
setStyle($pause, 'display', `none`)
|
||||
}
|
||||
}
|
||||
|
||||
function createMini() {
|
||||
const { $mini } = art.template
|
||||
if ($mini) {
|
||||
append($mini, $video)
|
||||
return setStyle($mini, 'display', 'flex')
|
||||
}
|
||||
else {
|
||||
const $mini = createElement('div')
|
||||
addClass($mini, 'art-mini-popup')
|
||||
append(document.body, $mini)
|
||||
art.template.$mini = $mini
|
||||
append($mini, $video)
|
||||
|
||||
const $close = append($mini, `<div class="art-mini-close"></div>`)
|
||||
append($close, icons.close)
|
||||
proxy($close, 'click', hideMini)
|
||||
|
||||
const $state = append($mini, `<div class="art-mini-state"></div>`)
|
||||
const $play = append($state, icons.play)
|
||||
const $pause = append($state, icons.pause)
|
||||
proxy($play, 'click', () => art.play())
|
||||
proxy($pause, 'click', () => art.pause())
|
||||
initState($play, $pause)
|
||||
art.on('video:playing', () => initState($play, $pause))
|
||||
art.on('video:pause', () => initState($play, $pause))
|
||||
art.on('video:timeupdate', () => initState($play, $pause))
|
||||
|
||||
proxy($mini, 'mousedown', (event) => {
|
||||
isDragging = event.button === 0
|
||||
lastPageX = event.pageX
|
||||
lastPageY = event.pageY
|
||||
})
|
||||
|
||||
art.on('document:mousemove', (event) => {
|
||||
if (isDragging) {
|
||||
addClass($mini, 'art-mini-dragging')
|
||||
const x = event.pageX - lastPageX
|
||||
const y = event.pageY - lastPageY
|
||||
setStyle($mini, 'transform', `translate(${x}px, ${y}px)`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function initState($play, $pause) {
|
||||
if (art.playing) {
|
||||
setStyle($play, 'display', `none`);
|
||||
setStyle($pause, 'display', `flex`);
|
||||
} else {
|
||||
setStyle($play, 'display', `flex`);
|
||||
setStyle($pause, 'display', `none`);
|
||||
art.on('document:mouseup', () => {
|
||||
if (isDragging) {
|
||||
isDragging = false
|
||||
removeClass($mini, 'art-mini-dragging')
|
||||
const rect = getRect($mini)
|
||||
storage.set('left', rect.left)
|
||||
storage.set('top', rect.top)
|
||||
setStyle($mini, 'left', `${rect.left}px`)
|
||||
setStyle($mini, 'top', `${rect.top}px`)
|
||||
setStyle($mini, 'transform', null)
|
||||
}
|
||||
})
|
||||
|
||||
return $mini
|
||||
}
|
||||
}
|
||||
|
||||
function createMini() {
|
||||
const { $mini } = art.template;
|
||||
if ($mini) {
|
||||
append($mini, $video);
|
||||
return setStyle($mini, 'display', 'flex');
|
||||
} else {
|
||||
const $mini = createElement('div');
|
||||
addClass($mini, 'art-mini-popup');
|
||||
append(document.body, $mini);
|
||||
art.template.$mini = $mini;
|
||||
append($mini, $video);
|
||||
function initMini() {
|
||||
const { $mini } = art.template
|
||||
const rect = getRect($mini)
|
||||
const top = window.innerHeight - rect.height - 50
|
||||
const left = window.innerWidth - rect.width - 50
|
||||
storage.set('top', top)
|
||||
storage.set('left', left)
|
||||
setStyle($mini, 'top', `${top}px`)
|
||||
setStyle($mini, 'left', `${left}px`)
|
||||
}
|
||||
|
||||
const $close = append($mini, `<div class="art-mini-close"></div>`);
|
||||
append($close, icons.close);
|
||||
proxy($close, 'click', hideMini);
|
||||
|
||||
const $state = append($mini, `<div class="art-mini-state"></div>`);
|
||||
const $play = append($state, icons.play);
|
||||
const $pause = append($state, icons.pause);
|
||||
proxy($play, 'click', () => art.play());
|
||||
proxy($pause, 'click', () => art.pause());
|
||||
initState($play, $pause);
|
||||
art.on('video:playing', () => initState($play, $pause));
|
||||
art.on('video:pause', () => initState($play, $pause));
|
||||
art.on('video:timeupdate', () => initState($play, $pause));
|
||||
|
||||
proxy($mini, 'mousedown', (event) => {
|
||||
isDragging = event.button === 0;
|
||||
lastPageX = event.pageX;
|
||||
lastPageY = event.pageY;
|
||||
});
|
||||
|
||||
art.on('document:mousemove', (event) => {
|
||||
if (isDragging) {
|
||||
addClass($mini, 'art-mini-dragging');
|
||||
const x = event.pageX - lastPageX;
|
||||
const y = event.pageY - lastPageY;
|
||||
setStyle($mini, 'transform', `translate(${x}px, ${y}px)`);
|
||||
}
|
||||
});
|
||||
|
||||
art.on('document:mouseup', () => {
|
||||
if (isDragging) {
|
||||
isDragging = false;
|
||||
removeClass($mini, 'art-mini-dragging');
|
||||
const rect = getRect($mini);
|
||||
storage.set('left', rect.left);
|
||||
storage.set('top', rect.top);
|
||||
setStyle($mini, 'left', `${rect.left}px`);
|
||||
setStyle($mini, 'top', `${rect.top}px`);
|
||||
setStyle($mini, 'transform', null);
|
||||
}
|
||||
});
|
||||
|
||||
return $mini;
|
||||
def(art, 'mini', {
|
||||
get() {
|
||||
return hasClass($player, 'art-mini')
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
art.state = 'mini'
|
||||
addClass($player, 'art-mini')
|
||||
const $mini = createMini()
|
||||
const top = storage.get('top')
|
||||
const left = storage.get('left')
|
||||
if (typeof top === 'number' && typeof left === 'number') {
|
||||
setStyle($mini, 'top', `${top}px`)
|
||||
setStyle($mini, 'left', `${left}px`)
|
||||
if (!isInViewport($mini)) {
|
||||
initMini()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initMini() {
|
||||
const { $mini } = art.template;
|
||||
const rect = getRect($mini);
|
||||
const top = window.innerHeight - rect.height - 50;
|
||||
const left = window.innerWidth - rect.width - 50;
|
||||
storage.set('top', top);
|
||||
storage.set('left', left);
|
||||
setStyle($mini, 'top', `${top}px`);
|
||||
setStyle($mini, 'left', `${left}px`);
|
||||
}
|
||||
|
||||
def(art, 'mini', {
|
||||
get() {
|
||||
return hasClass($player, 'art-mini');
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
art.state = 'mini';
|
||||
addClass($player, 'art-mini');
|
||||
const $mini = createMini();
|
||||
const top = storage.get('top');
|
||||
const left = storage.get('left');
|
||||
if (typeof top === 'number' && typeof left === 'number') {
|
||||
setStyle($mini, 'top', `${top}px`);
|
||||
setStyle($mini, 'left', `${left}px`);
|
||||
if (!isInViewport($mini)) {
|
||||
initMini();
|
||||
}
|
||||
} else {
|
||||
initMini();
|
||||
}
|
||||
art.emit('mini', true);
|
||||
} else {
|
||||
hideMini();
|
||||
}
|
||||
},
|
||||
});
|
||||
else {
|
||||
initMini()
|
||||
}
|
||||
art.emit('mini', true)
|
||||
}
|
||||
else {
|
||||
hideMini()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,49 +1,49 @@
|
||||
import { clamp, setStyle } from '../utils';
|
||||
import { clamp, setStyle } from '../utils'
|
||||
|
||||
export default function optionInit(art) {
|
||||
const {
|
||||
option,
|
||||
storage,
|
||||
template: { $video, $poster },
|
||||
} = art;
|
||||
const {
|
||||
option,
|
||||
storage,
|
||||
template: { $video, $poster },
|
||||
} = art
|
||||
|
||||
for (const key in option.moreVideoAttr) {
|
||||
art.attr(key, option.moreVideoAttr[key]);
|
||||
}
|
||||
for (const key in option.moreVideoAttr) {
|
||||
art.attr(key, option.moreVideoAttr[key])
|
||||
}
|
||||
|
||||
if (option.muted) {
|
||||
art.muted = option.muted;
|
||||
}
|
||||
if (option.muted) {
|
||||
art.muted = option.muted
|
||||
}
|
||||
|
||||
if (option.volume) {
|
||||
$video.volume = clamp(option.volume, 0, 1);
|
||||
}
|
||||
if (option.volume) {
|
||||
$video.volume = clamp(option.volume, 0, 1)
|
||||
}
|
||||
|
||||
const volumeStorage = storage.get('volume');
|
||||
if (typeof volumeStorage === 'number') {
|
||||
$video.volume = clamp(volumeStorage, 0, 1);
|
||||
}
|
||||
const volumeStorage = storage.get('volume')
|
||||
if (typeof volumeStorage === 'number') {
|
||||
$video.volume = clamp(volumeStorage, 0, 1)
|
||||
}
|
||||
|
||||
if (option.poster) {
|
||||
setStyle($poster, 'backgroundImage', `url(${option.poster})`);
|
||||
}
|
||||
if (option.poster) {
|
||||
setStyle($poster, 'backgroundImage', `url(${option.poster})`)
|
||||
}
|
||||
|
||||
if (option.autoplay) {
|
||||
$video.autoplay = option.autoplay;
|
||||
}
|
||||
if (option.autoplay) {
|
||||
$video.autoplay = option.autoplay
|
||||
}
|
||||
|
||||
if (option.playsInline) {
|
||||
$video.playsInline = true;
|
||||
$video['webkit-playsinline'] = true;
|
||||
}
|
||||
if (option.playsInline) {
|
||||
$video.playsInline = true
|
||||
$video['webkit-playsinline'] = true
|
||||
}
|
||||
|
||||
if (option.theme) {
|
||||
option.cssVar['--art-theme'] = option.theme;
|
||||
}
|
||||
if (option.theme) {
|
||||
option.cssVar['--art-theme'] = option.theme
|
||||
}
|
||||
|
||||
for (const key in option.cssVar) {
|
||||
art.cssVar(key, option.cssVar[key]);
|
||||
}
|
||||
for (const key in option.cssVar) {
|
||||
art.cssVar(key, option.cssVar[key])
|
||||
}
|
||||
|
||||
art.url = option.url;
|
||||
art.url = option.url
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function pauseMix(art) {
|
||||
const {
|
||||
template: { $video },
|
||||
i18n,
|
||||
notice,
|
||||
} = art;
|
||||
const {
|
||||
template: { $video },
|
||||
i18n,
|
||||
notice,
|
||||
} = art
|
||||
|
||||
def(art, 'pause', {
|
||||
value() {
|
||||
const result = $video.pause();
|
||||
notice.show = i18n.get('Pause');
|
||||
art.emit('pause');
|
||||
return result;
|
||||
},
|
||||
});
|
||||
def(art, 'pause', {
|
||||
value() {
|
||||
const result = $video.pause()
|
||||
notice.show = i18n.get('Pause')
|
||||
art.emit('pause')
|
||||
return result
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,83 +1,87 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
function nativePip(art) {
|
||||
const {
|
||||
template: { $video },
|
||||
proxy,
|
||||
notice,
|
||||
} = art;
|
||||
const {
|
||||
template: { $video },
|
||||
proxy,
|
||||
notice,
|
||||
} = art
|
||||
|
||||
$video.disablePictureInPicture = false;
|
||||
$video.disablePictureInPicture = false
|
||||
|
||||
def(art, 'pip', {
|
||||
get() {
|
||||
return document.pictureInPictureElement;
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
art.state = 'pip';
|
||||
$video.requestPictureInPicture().catch((err) => {
|
||||
notice.show = err;
|
||||
throw err;
|
||||
});
|
||||
} else {
|
||||
document.exitPictureInPicture().catch((err) => {
|
||||
notice.show = err;
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
def(art, 'pip', {
|
||||
get() {
|
||||
return document.pictureInPictureElement
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
art.state = 'pip'
|
||||
$video.requestPictureInPicture().catch((err) => {
|
||||
notice.show = err
|
||||
throw err
|
||||
})
|
||||
}
|
||||
else {
|
||||
document.exitPictureInPicture().catch((err) => {
|
||||
notice.show = err
|
||||
throw err
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
proxy($video, 'enterpictureinpicture', () => {
|
||||
art.emit('pip', true);
|
||||
});
|
||||
proxy($video, 'enterpictureinpicture', () => {
|
||||
art.emit('pip', true)
|
||||
})
|
||||
|
||||
proxy($video, 'leavepictureinpicture', () => {
|
||||
art.emit('pip', false);
|
||||
});
|
||||
proxy($video, 'leavepictureinpicture', () => {
|
||||
art.emit('pip', false)
|
||||
})
|
||||
}
|
||||
|
||||
function webkitPip(art) {
|
||||
const { $video } = art.template;
|
||||
const { $video } = art.template
|
||||
|
||||
$video.webkitSetPresentationMode('inline');
|
||||
$video.webkitSetPresentationMode('inline')
|
||||
|
||||
def(art, 'pip', {
|
||||
get() {
|
||||
return $video.webkitPresentationMode === 'picture-in-picture';
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
art.state = 'pip';
|
||||
$video.webkitSetPresentationMode('picture-in-picture');
|
||||
art.emit('pip', true);
|
||||
} else {
|
||||
$video.webkitSetPresentationMode('inline');
|
||||
art.emit('pip', false);
|
||||
}
|
||||
},
|
||||
});
|
||||
def(art, 'pip', {
|
||||
get() {
|
||||
return $video.webkitPresentationMode === 'picture-in-picture'
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
art.state = 'pip'
|
||||
$video.webkitSetPresentationMode('picture-in-picture')
|
||||
art.emit('pip', true)
|
||||
}
|
||||
else {
|
||||
$video.webkitSetPresentationMode('inline')
|
||||
art.emit('pip', false)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export default function pipMix(art) {
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
template: { $video },
|
||||
} = art;
|
||||
if (document.pictureInPictureEnabled) {
|
||||
nativePip(art);
|
||||
} else if ($video.webkitSupportsPresentationMode) {
|
||||
webkitPip(art);
|
||||
} else {
|
||||
def(art, 'pip', {
|
||||
get() {
|
||||
return false;
|
||||
},
|
||||
set() {
|
||||
notice.show = i18n.get('PIP Not Supported');
|
||||
},
|
||||
});
|
||||
}
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
template: { $video },
|
||||
} = art
|
||||
if (document.pictureInPictureEnabled) {
|
||||
nativePip(art)
|
||||
}
|
||||
else if ($video.webkitSupportsPresentationMode) {
|
||||
webkitPip(art)
|
||||
}
|
||||
else {
|
||||
def(art, 'pip', {
|
||||
get() {
|
||||
return false
|
||||
},
|
||||
set() {
|
||||
notice.show = i18n.get('PIP Not Supported')
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,30 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function playMix(art) {
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
option,
|
||||
constructor: { instances },
|
||||
template: { $video },
|
||||
} = art;
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
option,
|
||||
constructor: { instances },
|
||||
template: { $video },
|
||||
} = art
|
||||
|
||||
def(art, 'play', {
|
||||
value: async function () {
|
||||
const result = await $video.play();
|
||||
notice.show = i18n.get('Play');
|
||||
art.emit('play');
|
||||
def(art, 'play', {
|
||||
async value() {
|
||||
const result = await $video.play()
|
||||
notice.show = i18n.get('Play')
|
||||
art.emit('play')
|
||||
|
||||
if (option.mutex) {
|
||||
for (let index = 0; index < instances.length; index++) {
|
||||
const instance = instances[index];
|
||||
if (instance !== art) {
|
||||
instance.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (option.mutex) {
|
||||
for (let index = 0; index < instances.length; index++) {
|
||||
const instance = instances[index]
|
||||
if (instance !== art) {
|
||||
instance.pause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
return result
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,24 +1,26 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function playbackRateMix(art) {
|
||||
const {
|
||||
template: { $video },
|
||||
i18n,
|
||||
notice,
|
||||
} = art;
|
||||
const {
|
||||
template: { $video },
|
||||
i18n,
|
||||
notice,
|
||||
} = art
|
||||
|
||||
def(art, 'playbackRate', {
|
||||
get() {
|
||||
return $video.playbackRate;
|
||||
},
|
||||
set(rate) {
|
||||
if (rate) {
|
||||
if (rate === $video.playbackRate) return;
|
||||
$video.playbackRate = rate;
|
||||
notice.show = `${i18n.get('Rate')}: ${rate === 1.0 ? i18n.get('Normal') : `${rate}x`}`;
|
||||
} else {
|
||||
art.playbackRate = 1;
|
||||
}
|
||||
},
|
||||
});
|
||||
def(art, 'playbackRate', {
|
||||
get() {
|
||||
return $video.playbackRate
|
||||
},
|
||||
set(rate) {
|
||||
if (rate) {
|
||||
if (rate === $video.playbackRate)
|
||||
return
|
||||
$video.playbackRate = rate
|
||||
notice.show = `${i18n.get('Rate')}: ${rate === 1.0 ? i18n.get('Normal') : `${rate}x`}`
|
||||
}
|
||||
else {
|
||||
art.playbackRate = 1
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function playedMix(art) {
|
||||
def(art, 'played', {
|
||||
get: () => art.currentTime / art.duration,
|
||||
});
|
||||
def(art, 'played', {
|
||||
get: () => art.currentTime / art.duration,
|
||||
})
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function playingMix(art) {
|
||||
const { $video } = art.template;
|
||||
def(art, 'playing', {
|
||||
get: () => {
|
||||
if (typeof $video.playing === 'boolean') return $video.playing;
|
||||
return !!($video.currentTime > 0 && !$video.paused && !$video.ended && $video.readyState > 2);
|
||||
},
|
||||
});
|
||||
const { $video } = art.template
|
||||
def(art, 'playing', {
|
||||
get: () => {
|
||||
if (typeof $video.playing === 'boolean')
|
||||
return $video.playing
|
||||
return !!($video.currentTime > 0 && !$video.paused && !$video.ended && $video.readyState > 2)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
import { def, setStyle } from '../utils';
|
||||
import { def, setStyle } from '../utils'
|
||||
|
||||
export default function posterMix(art) {
|
||||
const {
|
||||
template: { $poster },
|
||||
} = art;
|
||||
const {
|
||||
template: { $poster },
|
||||
} = art
|
||||
|
||||
def(art, 'poster', {
|
||||
get: () => {
|
||||
try {
|
||||
return $poster.style['backgroundImage'].match(/"(.*)"/)[1];
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
set(url) {
|
||||
setStyle($poster, 'backgroundImage', `url(${url})`);
|
||||
},
|
||||
});
|
||||
def(art, 'poster', {
|
||||
get: () => {
|
||||
try {
|
||||
return $poster.style.backgroundImage.match(/"(.*)"/)[1]
|
||||
}
|
||||
catch {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
set(url) {
|
||||
setStyle($poster, 'backgroundImage', `url(${url})`)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,25 +1,25 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function qualityMix(art) {
|
||||
def(art, 'quality', {
|
||||
set(quality) {
|
||||
const { controls, notice, i18n } = art;
|
||||
const qualityDefault = quality.find((item) => item.default) || quality[0];
|
||||
controls.update({
|
||||
name: 'quality',
|
||||
position: 'right',
|
||||
index: 10,
|
||||
style: {
|
||||
marginRight: '10px',
|
||||
},
|
||||
html: qualityDefault?.html || '',
|
||||
selector: quality,
|
||||
async onSelect(item) {
|
||||
await art.switchQuality(item.url);
|
||||
notice.show = `${i18n.get('Switch Video')}: ${item.html}`;
|
||||
return item.html;
|
||||
},
|
||||
});
|
||||
def(art, 'quality', {
|
||||
set(quality) {
|
||||
const { controls, notice, i18n } = art
|
||||
const qualityDefault = quality.find(item => item.default) || quality[0]
|
||||
controls.update({
|
||||
name: 'quality',
|
||||
position: 'right',
|
||||
index: 10,
|
||||
style: {
|
||||
marginRight: '10px',
|
||||
},
|
||||
});
|
||||
html: qualityDefault?.html || '',
|
||||
selector: quality,
|
||||
async onSelect(item) {
|
||||
await art.switchQuality(item.url)
|
||||
notice.show = `${i18n.get('Switch Video')}: ${item.html}`
|
||||
return item.html
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
import { def, getRect } from '../utils';
|
||||
import { def, getRect } from '../utils'
|
||||
|
||||
export default function rectMix(art) {
|
||||
def(art, 'rect', {
|
||||
get: () => {
|
||||
return getRect(art.template.$player);
|
||||
},
|
||||
});
|
||||
def(art, 'rect', {
|
||||
get: () => {
|
||||
return getRect(art.template.$player)
|
||||
},
|
||||
})
|
||||
|
||||
const keys = ['bottom', 'height', 'left', 'right', 'top', 'width'];
|
||||
for (let index = 0; index < keys.length; index++) {
|
||||
const key = keys[index];
|
||||
def(art, key, {
|
||||
get: () => {
|
||||
return art.rect[key];
|
||||
},
|
||||
});
|
||||
}
|
||||
const keys = ['bottom', 'height', 'left', 'right', 'top', 'width']
|
||||
for (let index = 0; index < keys.length; index++) {
|
||||
const key = keys[index]
|
||||
def(art, key, {
|
||||
get: () => {
|
||||
return art.rect[key]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
def(art, 'x', {
|
||||
get: () => {
|
||||
return art.left + window.pageXOffset;
|
||||
},
|
||||
});
|
||||
def(art, 'x', {
|
||||
get: () => {
|
||||
return art.left + window.pageXOffset
|
||||
},
|
||||
})
|
||||
|
||||
def(art, 'y', {
|
||||
get: () => {
|
||||
return art.top + window.pageYOffset;
|
||||
},
|
||||
});
|
||||
def(art, 'y', {
|
||||
get: () => {
|
||||
return art.top + window.pageYOffset
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,52 +1,54 @@
|
||||
import { secondToTime, download, def, createElement } from '../utils';
|
||||
import { createElement, def, download, secondToTime } from '../utils'
|
||||
|
||||
export default function screenshotMix(art) {
|
||||
const {
|
||||
notice,
|
||||
template: { $video },
|
||||
} = art;
|
||||
const {
|
||||
notice,
|
||||
template: { $video },
|
||||
} = art
|
||||
|
||||
const $canvas = createElement('canvas');
|
||||
const $canvas = createElement('canvas')
|
||||
|
||||
def(art, 'getDataURL', {
|
||||
value: () =>
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
$canvas.width = $video.videoWidth;
|
||||
$canvas.height = $video.videoHeight;
|
||||
$canvas.getContext('2d').drawImage($video, 0, 0);
|
||||
resolve($canvas.toDataURL('image/png'));
|
||||
} catch (err) {
|
||||
notice.show = err;
|
||||
reject(err);
|
||||
}
|
||||
}),
|
||||
});
|
||||
def(art, 'getDataURL', {
|
||||
value: () =>
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
$canvas.width = $video.videoWidth
|
||||
$canvas.height = $video.videoHeight
|
||||
$canvas.getContext('2d').drawImage($video, 0, 0)
|
||||
resolve($canvas.toDataURL('image/png'))
|
||||
}
|
||||
catch (err) {
|
||||
notice.show = err
|
||||
reject(err)
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
def(art, 'getBlobUrl', {
|
||||
value: () =>
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
$canvas.width = $video.videoWidth;
|
||||
$canvas.height = $video.videoHeight;
|
||||
$canvas.getContext('2d').drawImage($video, 0, 0);
|
||||
$canvas.toBlob((blob) => {
|
||||
resolve(URL.createObjectURL(blob));
|
||||
});
|
||||
} catch (err) {
|
||||
notice.show = err;
|
||||
reject(err);
|
||||
}
|
||||
}),
|
||||
});
|
||||
def(art, 'getBlobUrl', {
|
||||
value: () =>
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
$canvas.width = $video.videoWidth
|
||||
$canvas.height = $video.videoHeight
|
||||
$canvas.getContext('2d').drawImage($video, 0, 0)
|
||||
$canvas.toBlob((blob) => {
|
||||
resolve(URL.createObjectURL(blob))
|
||||
})
|
||||
}
|
||||
catch (err) {
|
||||
notice.show = err
|
||||
reject(err)
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
def(art, 'screenshot', {
|
||||
value: async (name) => {
|
||||
const dataUri = await art.getDataURL();
|
||||
const fileName = name || `artplayer_${secondToTime($video.currentTime)}`;
|
||||
download(dataUri, `${fileName}.png`);
|
||||
art.emit('screenshot', dataUri);
|
||||
return dataUri;
|
||||
},
|
||||
});
|
||||
def(art, 'screenshot', {
|
||||
value: async (name) => {
|
||||
const dataUri = await art.getDataURL()
|
||||
const fileName = name || `artplayer_${secondToTime($video.currentTime)}`
|
||||
download(dataUri, `${fileName}.png`)
|
||||
art.emit('screenshot', dataUri)
|
||||
return dataUri
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
import { secondToTime, def } from '../utils';
|
||||
import { def, secondToTime } from '../utils'
|
||||
|
||||
export default function seekMix(art) {
|
||||
const { notice } = art;
|
||||
const { notice } = art
|
||||
|
||||
def(art, 'seek', {
|
||||
set(time) {
|
||||
art.currentTime = time;
|
||||
if (art.duration) {
|
||||
notice.show = `${secondToTime(art.currentTime)} / ${secondToTime(art.duration)}`;
|
||||
}
|
||||
art.emit('seek', art.currentTime);
|
||||
},
|
||||
});
|
||||
def(art, 'seek', {
|
||||
set(time) {
|
||||
art.currentTime = time
|
||||
if (art.duration) {
|
||||
notice.show = `${secondToTime(art.currentTime)} / ${secondToTime(art.duration)}`
|
||||
}
|
||||
art.emit('seek', art.currentTime)
|
||||
},
|
||||
})
|
||||
|
||||
def(art, 'forward', {
|
||||
set(time) {
|
||||
art.seek = art.currentTime + time;
|
||||
},
|
||||
});
|
||||
def(art, 'forward', {
|
||||
set(time) {
|
||||
art.seek = art.currentTime + time
|
||||
},
|
||||
})
|
||||
|
||||
def(art, 'backward', {
|
||||
set(time) {
|
||||
art.seek = art.currentTime - time;
|
||||
},
|
||||
});
|
||||
def(art, 'backward', {
|
||||
set(time) {
|
||||
art.seek = art.currentTime - time
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function stateMix(art) {
|
||||
const states = ['mini', 'pip', 'fullscreen', 'fullscreenWeb'];
|
||||
def(art, 'state', {
|
||||
get: () => states.find((name) => art[name]) || 'standard',
|
||||
set(name) {
|
||||
for (let index = 0; index < states.length; index++) {
|
||||
const prop = states[index];
|
||||
if (prop !== name && art[prop]) {
|
||||
art[prop] = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const states = ['mini', 'pip', 'fullscreen', 'fullscreenWeb']
|
||||
def(art, 'state', {
|
||||
get: () => states.find(name => art[name]) || 'standard',
|
||||
set(name) {
|
||||
for (let index = 0; index < states.length; index++) {
|
||||
const prop = states[index]
|
||||
if (prop !== name && art[prop]) {
|
||||
art[prop] = false
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,27 +1,28 @@
|
||||
import { def, clamp } from '../utils';
|
||||
import { clamp, def } from '../utils'
|
||||
|
||||
export default function subtitleOffsetMix(art) {
|
||||
const { notice, i18n, template } = art;
|
||||
const { notice, i18n, template } = art
|
||||
|
||||
def(art, 'subtitleOffset', {
|
||||
get() {
|
||||
return template.$track?.offset || 0;
|
||||
},
|
||||
set(value) {
|
||||
const { cues } = art.subtitle;
|
||||
if (!template.$track || cues.length === 0) return;
|
||||
const offset = clamp(value, -10, 10);
|
||||
template.$track.offset = offset;
|
||||
for (let index = 0; index < cues.length; index++) {
|
||||
const cue = cues[index];
|
||||
cue.originalStartTime = cue.originalStartTime ?? cue.startTime;
|
||||
cue.originalEndTime = cue.originalEndTime ?? cue.endTime;
|
||||
cue.startTime = clamp(cue.originalStartTime + offset, 0, art.duration);
|
||||
cue.endTime = clamp(cue.originalEndTime + offset, 0, art.duration);
|
||||
}
|
||||
art.subtitle.update();
|
||||
notice.show = `${i18n.get('Subtitle Offset')}: ${value}s`;
|
||||
art.emit('subtitleOffset', value);
|
||||
},
|
||||
});
|
||||
def(art, 'subtitleOffset', {
|
||||
get() {
|
||||
return template.$track?.offset || 0
|
||||
},
|
||||
set(value) {
|
||||
const { cues } = art.subtitle
|
||||
if (!template.$track || cues.length === 0)
|
||||
return
|
||||
const offset = clamp(value, -10, 10)
|
||||
template.$track.offset = offset
|
||||
for (let index = 0; index < cues.length; index++) {
|
||||
const cue = cues[index]
|
||||
cue.originalStartTime = cue.originalStartTime ?? cue.startTime
|
||||
cue.originalEndTime = cue.originalEndTime ?? cue.endTime
|
||||
cue.startTime = clamp(cue.originalStartTime + offset, 0, art.duration)
|
||||
cue.endTime = clamp(cue.originalEndTime + offset, 0, art.duration)
|
||||
}
|
||||
art.subtitle.update()
|
||||
notice.show = `${i18n.get('Subtitle Offset')}: ${value}s`
|
||||
art.emit('subtitleOffset', value)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,49 +1,50 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function switchMix(art) {
|
||||
function switchUrl(url, currentTime) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (url === art.url) return;
|
||||
const { playing, aspectRatio, playbackRate } = art;
|
||||
function switchUrl(url, currentTime) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (url === art.url)
|
||||
return
|
||||
const { playing, aspectRatio, playbackRate } = art
|
||||
|
||||
art.pause();
|
||||
art.url = url;
|
||||
art.notice.show = '';
|
||||
art.pause()
|
||||
art.url = url
|
||||
art.notice.show = ''
|
||||
|
||||
art.once('video:error', reject);
|
||||
art.once('video:error', reject)
|
||||
|
||||
art.once('video:loadedmetadata', () => {
|
||||
art.currentTime = currentTime;
|
||||
});
|
||||
art.once('video:loadedmetadata', () => {
|
||||
art.currentTime = currentTime
|
||||
})
|
||||
|
||||
art.once('video:canplay', async () => {
|
||||
art.playbackRate = playbackRate;
|
||||
art.aspectRatio = aspectRatio;
|
||||
art.once('video:canplay', async () => {
|
||||
art.playbackRate = playbackRate
|
||||
art.aspectRatio = aspectRatio
|
||||
|
||||
if (playing) {
|
||||
await art.play();
|
||||
}
|
||||
if (playing) {
|
||||
await art.play()
|
||||
}
|
||||
|
||||
art.notice.show = '';
|
||||
art.notice.show = ''
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
def(art, 'switchQuality', {
|
||||
value: (url) => {
|
||||
return switchUrl(url, art.currentTime);
|
||||
},
|
||||
});
|
||||
def(art, 'switchQuality', {
|
||||
value: (url) => {
|
||||
return switchUrl(url, art.currentTime)
|
||||
},
|
||||
})
|
||||
|
||||
def(art, 'switchUrl', {
|
||||
value: (url) => {
|
||||
return switchUrl(url, 0);
|
||||
},
|
||||
});
|
||||
def(art, 'switchUrl', {
|
||||
value: (url) => {
|
||||
return switchUrl(url, 0)
|
||||
},
|
||||
})
|
||||
|
||||
def(art, 'switch', {
|
||||
set: art.switchUrl,
|
||||
});
|
||||
def(art, 'switch', {
|
||||
set: art.switchUrl,
|
||||
})
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function themeMix(art) {
|
||||
def(art, 'theme', {
|
||||
get() {
|
||||
return art.cssVar('--art-theme');
|
||||
},
|
||||
set(theme) {
|
||||
art.cssVar('--art-theme', theme);
|
||||
},
|
||||
});
|
||||
def(art, 'theme', {
|
||||
get() {
|
||||
return art.cssVar('--art-theme')
|
||||
},
|
||||
set(theme) {
|
||||
art.cssVar('--art-theme', theme)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,105 +1,111 @@
|
||||
import { def, setStyle, isMobile, loadImg } from '../utils';
|
||||
import { def, isMobile, loadImg, setStyle } from '../utils'
|
||||
|
||||
export default function thumbnailsMix(art) {
|
||||
const {
|
||||
events,
|
||||
option,
|
||||
template: { $progress, $video },
|
||||
} = art;
|
||||
const {
|
||||
events,
|
||||
option,
|
||||
template: { $progress, $video },
|
||||
} = art
|
||||
|
||||
let timer = null;
|
||||
let image = null;
|
||||
let loading = false;
|
||||
let isLoad = false;
|
||||
let isHover = false;
|
||||
let timer = null
|
||||
let image = null
|
||||
let loading = false
|
||||
let isLoad = false
|
||||
let isHover = false
|
||||
|
||||
function reset() {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
image = null;
|
||||
loading = false;
|
||||
isLoad = false;
|
||||
function reset() {
|
||||
clearTimeout(timer)
|
||||
timer = null
|
||||
image = null
|
||||
loading = false
|
||||
isLoad = false
|
||||
}
|
||||
|
||||
function showThumbnails(posWidth) {
|
||||
const $thumbnails = art.controls?.thumbnails
|
||||
if (!$thumbnails)
|
||||
return
|
||||
|
||||
const { number, column, width, height, scale } = option.thumbnails
|
||||
const width2 = width * scale || image.naturalWidth / column
|
||||
const height2 = height * scale || width2 / ($video.videoWidth / $video.videoHeight)
|
||||
const perWidth = $progress.clientWidth / number
|
||||
const perIndex = Math.floor(posWidth / perWidth)
|
||||
const yIndex = Math.ceil(perIndex / column) - 1
|
||||
const xIndex = perIndex % column || column - 1
|
||||
setStyle($thumbnails, 'backgroundImage', `url(${image.src})`)
|
||||
setStyle($thumbnails, 'height', `${height2}px`)
|
||||
setStyle($thumbnails, 'width', `${width2}px`)
|
||||
setStyle($thumbnails, 'backgroundPosition', `-${xIndex * width2}px -${yIndex * height2}px`)
|
||||
if (posWidth <= width2 / 2) {
|
||||
setStyle($thumbnails, 'left', 0)
|
||||
}
|
||||
|
||||
function showThumbnails(posWidth) {
|
||||
const $thumbnails = art.controls?.thumbnails;
|
||||
if (!$thumbnails) return;
|
||||
|
||||
const { number, column, width, height, scale } = option.thumbnails;
|
||||
const width2 = width * scale || image.naturalWidth / column;
|
||||
const height2 = height * scale || width2 / ($video.videoWidth / $video.videoHeight);
|
||||
const perWidth = $progress.clientWidth / number;
|
||||
const perIndex = Math.floor(posWidth / perWidth);
|
||||
const yIndex = Math.ceil(perIndex / column) - 1;
|
||||
const xIndex = perIndex % column || column - 1;
|
||||
setStyle($thumbnails, 'backgroundImage', `url(${image.src})`);
|
||||
setStyle($thumbnails, 'height', `${height2}px`);
|
||||
setStyle($thumbnails, 'width', `${width2}px`);
|
||||
setStyle($thumbnails, 'backgroundPosition', `-${xIndex * width2}px -${yIndex * height2}px`);
|
||||
if (posWidth <= width2 / 2) {
|
||||
setStyle($thumbnails, 'left', 0);
|
||||
} else if (posWidth > $progress.clientWidth - width2 / 2) {
|
||||
setStyle($thumbnails, 'left', `${$progress.clientWidth - width2}px`);
|
||||
} else {
|
||||
setStyle($thumbnails, 'left', `${posWidth - width2 / 2}px`);
|
||||
}
|
||||
else if (posWidth > $progress.clientWidth - width2 / 2) {
|
||||
setStyle($thumbnails, 'left', `${$progress.clientWidth - width2}px`)
|
||||
}
|
||||
else {
|
||||
setStyle($thumbnails, 'left', `${posWidth - width2 / 2}px`)
|
||||
}
|
||||
}
|
||||
|
||||
events.hover(
|
||||
$progress,
|
||||
() => {
|
||||
isHover = true;
|
||||
},
|
||||
() => {
|
||||
isHover = false;
|
||||
},
|
||||
);
|
||||
events.hover(
|
||||
$progress,
|
||||
() => {
|
||||
isHover = true
|
||||
},
|
||||
() => {
|
||||
isHover = false
|
||||
},
|
||||
)
|
||||
|
||||
art.on('setBar', async (type, percentage, event) => {
|
||||
const $thumbnails = art.controls?.thumbnails;
|
||||
const { url, scale } = option.thumbnails;
|
||||
if (!$thumbnails || !url) return;
|
||||
art.on('setBar', async (type, percentage, event) => {
|
||||
const $thumbnails = art.controls?.thumbnails
|
||||
const { url, scale } = option.thumbnails
|
||||
if (!$thumbnails || !url)
|
||||
return
|
||||
|
||||
const isMobileDragging = type === 'played' && event && isMobile;
|
||||
const isMobileDragging = type === 'played' && event && isMobile
|
||||
|
||||
if (type === 'hover' || isMobileDragging) {
|
||||
if (!loading) {
|
||||
loading = true;
|
||||
image = await loadImg(url, scale);
|
||||
isLoad = true;
|
||||
}
|
||||
if (type === 'hover' || isMobileDragging) {
|
||||
if (!loading) {
|
||||
loading = true
|
||||
image = await loadImg(url, scale)
|
||||
isLoad = true
|
||||
}
|
||||
|
||||
if (!isLoad || !isHover) return;
|
||||
if (!isLoad || !isHover)
|
||||
return
|
||||
|
||||
const width = $progress.clientWidth * percentage;
|
||||
setStyle($thumbnails, 'display', 'flex');
|
||||
const width = $progress.clientWidth * percentage
|
||||
setStyle($thumbnails, 'display', 'flex')
|
||||
|
||||
if (width > 0 && width < $progress.clientWidth) {
|
||||
showThumbnails(width);
|
||||
} else {
|
||||
if (!isMobile) {
|
||||
setStyle($thumbnails, 'display', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
if (isMobileDragging) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
setStyle($thumbnails, 'display', 'none');
|
||||
}, 500);
|
||||
}
|
||||
if (width > 0 && width < $progress.clientWidth) {
|
||||
showThumbnails(width)
|
||||
}
|
||||
else {
|
||||
if (!isMobile) {
|
||||
setStyle($thumbnails, 'display', 'none')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
def(art, 'thumbnails', {
|
||||
get() {
|
||||
return art.option.thumbnails;
|
||||
},
|
||||
set(thumbnails) {
|
||||
if (thumbnails.url && !art.option.isLive) {
|
||||
art.option.thumbnails = thumbnails;
|
||||
reset();
|
||||
}
|
||||
},
|
||||
});
|
||||
if (isMobileDragging) {
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
setStyle($thumbnails, 'display', 'none')
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
def(art, 'thumbnails', {
|
||||
get() {
|
||||
return art.option.thumbnails
|
||||
},
|
||||
set(thumbnails) {
|
||||
if (thumbnails.url && !art.option.isLive) {
|
||||
art.option.thumbnails = thumbnails
|
||||
reset()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function toggleMix(art) {
|
||||
def(art, 'toggle', {
|
||||
value() {
|
||||
if (art.playing) {
|
||||
return art.pause();
|
||||
} else {
|
||||
return art.play();
|
||||
}
|
||||
},
|
||||
});
|
||||
def(art, 'toggle', {
|
||||
value() {
|
||||
if (art.playing) {
|
||||
return art.pause()
|
||||
}
|
||||
else {
|
||||
return art.play()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { def } from '../utils';
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function typeMix(art) {
|
||||
def(art, 'type', {
|
||||
get() {
|
||||
return art.option.type;
|
||||
},
|
||||
set(type) {
|
||||
art.option.type = type;
|
||||
},
|
||||
});
|
||||
def(art, 'type', {
|
||||
get() {
|
||||
return art.option.type
|
||||
},
|
||||
set(type) {
|
||||
art.option.type = type
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,42 +1,44 @@
|
||||
import { getExt, def, sleep } from '../utils';
|
||||
import { def, getExt, sleep } from '../utils'
|
||||
|
||||
export default function urlMix(art) {
|
||||
const {
|
||||
option,
|
||||
template: { $video },
|
||||
} = art;
|
||||
const {
|
||||
option,
|
||||
template: { $video },
|
||||
} = art
|
||||
|
||||
def(art, 'url', {
|
||||
get() {
|
||||
return $video.src;
|
||||
},
|
||||
async set(newUrl) {
|
||||
if (newUrl) {
|
||||
const oldUrl = art.url;
|
||||
const typeName = option.type || getExt(newUrl);
|
||||
const typeCallback = option.customType[typeName];
|
||||
def(art, 'url', {
|
||||
get() {
|
||||
return $video.src
|
||||
},
|
||||
async set(newUrl) {
|
||||
if (newUrl) {
|
||||
const oldUrl = art.url
|
||||
const typeName = option.type || getExt(newUrl)
|
||||
const typeCallback = option.customType[typeName]
|
||||
|
||||
if (typeName && typeCallback) {
|
||||
await sleep();
|
||||
art.loading.show = true;
|
||||
typeCallback.call(art, $video, newUrl, art);
|
||||
} else {
|
||||
URL.revokeObjectURL(oldUrl);
|
||||
$video.src = newUrl;
|
||||
}
|
||||
if (typeName && typeCallback) {
|
||||
await sleep()
|
||||
art.loading.show = true
|
||||
typeCallback.call(art, $video, newUrl, art)
|
||||
}
|
||||
else {
|
||||
URL.revokeObjectURL(oldUrl)
|
||||
$video.src = newUrl
|
||||
}
|
||||
|
||||
if (oldUrl !== art.url) {
|
||||
art.option.url = newUrl;
|
||||
if (art.isReady && oldUrl) {
|
||||
art.once('video:canplay', () => {
|
||||
art.emit('restart', newUrl);
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await sleep();
|
||||
art.loading.show = true;
|
||||
}
|
||||
},
|
||||
});
|
||||
if (oldUrl !== art.url) {
|
||||
art.option.url = newUrl
|
||||
if (art.isReady && oldUrl) {
|
||||
art.once('video:canplay', () => {
|
||||
art.emit('restart', newUrl)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
await sleep()
|
||||
art.loading.show = true
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,29 +1,29 @@
|
||||
import { clamp, def } from '../utils';
|
||||
import { clamp, def } from '../utils'
|
||||
|
||||
export default function volumeMix(art) {
|
||||
const {
|
||||
template: { $video },
|
||||
i18n,
|
||||
notice,
|
||||
storage,
|
||||
} = art;
|
||||
const {
|
||||
template: { $video },
|
||||
i18n,
|
||||
notice,
|
||||
storage,
|
||||
} = art
|
||||
|
||||
def(art, 'volume', {
|
||||
get: () => $video.volume || 0,
|
||||
set: (percentage) => {
|
||||
$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);
|
||||
}
|
||||
},
|
||||
});
|
||||
def(art, 'volume', {
|
||||
get: () => $video.volume || 0,
|
||||
set: (percentage) => {
|
||||
$video.volume = clamp(percentage, 0, 1)
|
||||
notice.show = `${i18n.get('Volume')}: ${Number.parseInt($video.volume * 100, 10)}`
|
||||
if ($video.volume !== 0) {
|
||||
storage.set('volume', $video.volume)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
def(art, 'muted', {
|
||||
get: () => $video.muted,
|
||||
set: (muted) => {
|
||||
$video.muted = muted;
|
||||
art.emit('muted', muted);
|
||||
},
|
||||
});
|
||||
def(art, 'muted', {
|
||||
get: () => $video.muted,
|
||||
set: (muted) => {
|
||||
$video.muted = muted
|
||||
art.emit('muted', muted)
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user