support segmented videos
This commit is contained in:
parent
15e770c988
commit
a042b39550
|
|
@ -17,7 +17,6 @@
|
|||
"no-implicit-globals": 1,
|
||||
"no-labels": 1,
|
||||
"no-multi-str": 1,
|
||||
"no-unused-expressions": 1,
|
||||
"comma-spacing": 1,
|
||||
"comma-style": 1,
|
||||
"func-call-spacing": 1,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@
|
|||
<link rel="stylesheet" href="../dist/DPlayer.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<a href="https://github.com/DIYgod/DPlayer" target="_blank" class="github-corner"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
|
||||
<div class="container">
|
||||
<h1>DPlayer</h1>
|
||||
<h2>Wow, such a lovely HTML5 danmaku video player</h2>
|
||||
|
|
@ -61,6 +60,8 @@
|
|||
<div class="dplayer" id="dplayer3"></div>
|
||||
<h3>FLV format support</h3>
|
||||
<div class="dplayer" id="dplayer4"></div>
|
||||
<h3>Segmented videos</h3>
|
||||
<div class="dplayer" id="dplayer5"></div>
|
||||
</div>
|
||||
<script src="https://rawgit.com/mrdoob/stats.js/master/build/stats.min.js"></script>
|
||||
<script src="../plugin/flv.min.js"></script>
|
||||
|
|
@ -180,6 +181,28 @@
|
|||
}
|
||||
});
|
||||
|
||||
// Segmented videos
|
||||
var dp5 = new DPlayer({
|
||||
element: document.getElementById('dplayer5'),
|
||||
autoplay: false,
|
||||
theme: '#FADFA3',
|
||||
loop: true,
|
||||
screenshot: true,
|
||||
hotkey: true,
|
||||
preload: 'metadata',
|
||||
video: {
|
||||
url: ['http://devtest.qiniudn.com/若能绽放光芒0.mp4', 'http://devtest.qiniudn.com/若能绽放光芒1.mp4', 'http://devtest.qiniudn.com/若能绽放光芒2.mp4', 'http://devtest.qiniudn.com/若能绽放光芒3.mp4', 'http://devtest.qiniudn.com/若能绽放光芒4.mp4', 'http://devtest.qiniudn.com/若能绽放光芒5.mp4', 'http://devtest.qiniudn.com/若能绽放光芒6.mp4', 'http://devtest.qiniudn.com/若能绽放光芒7.mp4', 'http://devtest.qiniudn.com/若能绽放光芒8.mp4'],
|
||||
pic: 'http://devtest.qiniudn.com/若能绽放光芒.png',
|
||||
type: 'normal',
|
||||
},
|
||||
danmaku: {
|
||||
id: '9E2E3368B56CDBB40',
|
||||
api: 'https://api.prprpr.me/dplayer/',
|
||||
token: 'tokendemo',
|
||||
maximum: 3000
|
||||
}
|
||||
});
|
||||
|
||||
// stats.js: JavaScript Performance Monitor
|
||||
var stats = new Stats();
|
||||
stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
|
||||
|
|
@ -193,5 +216,6 @@
|
|||
}
|
||||
requestAnimationFrame(animate);
|
||||
</script>
|
||||
<a href="https://github.com/DIYgod/DPlayer" target="_blank" class="github-corner"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
194
src/DPlayer.js
194
src/DPlayer.js
|
|
@ -1,10 +1,12 @@
|
|||
console.log('\n %c DPlayer 1.2.0 %c http://dplayer.js.org \n\n', 'color: #fadfa3; background: #030307; padding:5px 0;', 'background: #fadfa3; padding:5px 0;');
|
||||
|
||||
require('./DPlayer.scss');
|
||||
const utils = require('./utils.js');
|
||||
const svg = require('./svg.js');
|
||||
const handleOption = require('./option.js');
|
||||
const i18n = require('./i18n.js');
|
||||
const html = require('./html.js');
|
||||
const Video = require('./video.js');
|
||||
const isMobile = /mobile/i.test(window.navigator.userAgent);
|
||||
|
||||
let index = 0;
|
||||
|
|
@ -65,8 +67,8 @@ class DPlayer {
|
|||
document.head.appendChild(arrowStyle);
|
||||
}
|
||||
|
||||
// get this video object
|
||||
this.video = this.element.getElementsByClassName('dplayer-video')[0];
|
||||
// get this video manager
|
||||
this.video = new Video(this.element.getElementsByClassName('dplayer-video'));
|
||||
|
||||
// Support HTTP Live Streaming
|
||||
let enablehls;
|
||||
|
|
@ -82,7 +84,7 @@ class DPlayer {
|
|||
if (enablehls && Hls.isSupported()) {
|
||||
// this.element.getElementsByClassName('dplayer-time')[0].style.display = 'none';
|
||||
const hls = new Hls();
|
||||
hls.attachMedia(this.video);
|
||||
hls.attachMedia(this.video.current);
|
||||
hls.on(Hls.Events.MEDIA_ATTACHED, () => {
|
||||
hls.loadSource(this.option.video.url);
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
|
||||
|
|
@ -107,7 +109,7 @@ class DPlayer {
|
|||
type: 'flv',
|
||||
url: this.option.video.url
|
||||
});
|
||||
flvPlayer.attachMediaElement(this.video);
|
||||
flvPlayer.attachMediaElement(this.video.current);
|
||||
flvPlayer.load();
|
||||
}
|
||||
|
||||
|
|
@ -146,43 +148,6 @@ class DPlayer {
|
|||
conMask.addEventListener('click', toggleController);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse second to 00:00 format
|
||||
*
|
||||
* @param {Number} second
|
||||
* @return {String} 00:00 format
|
||||
*/
|
||||
const secondToTime = (second) => {
|
||||
const add0 = (num) => num < 10 ? '0' + num : '' + num;
|
||||
const min = parseInt(second / 60);
|
||||
const sec = parseInt(second - min * 60);
|
||||
return add0(min) + ':' + add0(sec);
|
||||
};
|
||||
|
||||
/**
|
||||
* control play progress
|
||||
*/
|
||||
// get element's view position
|
||||
const getElementViewLeft = (element) => {
|
||||
let actualLeft = element.offsetLeft;
|
||||
let current = element.offsetParent;
|
||||
const elementScrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft;
|
||||
if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement) {
|
||||
while (current !== null) {
|
||||
actualLeft += current.offsetLeft;
|
||||
current = current.offsetParent;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (current !== null && current !== this.element) {
|
||||
actualLeft += current.offsetLeft;
|
||||
current = current.offsetParent;
|
||||
}
|
||||
}
|
||||
return actualLeft - elementScrollLeft;
|
||||
};
|
||||
|
||||
const bar = {};
|
||||
bar.playedBar = this.element.getElementsByClassName('dplayer-played')[0];
|
||||
bar.loadedBar = this.element.getElementsByClassName('dplayer-loaded')[0];
|
||||
|
|
@ -191,9 +156,9 @@ class DPlayer {
|
|||
let barWidth;
|
||||
|
||||
if (this.option.danmaku) {
|
||||
this.video.addEventListener('seeking', () => {
|
||||
this.video.on('all', 'seeking', () => {
|
||||
for (let i = 0; i < this.dan.length; i++) {
|
||||
if (this.dan[i].time >= this.video.currentTime) {
|
||||
if (this.dan[i].time >= this.video.currentTime()) {
|
||||
this.danIndex = i;
|
||||
return;
|
||||
}
|
||||
|
|
@ -209,30 +174,30 @@ class DPlayer {
|
|||
this.setTime = () => {
|
||||
this.playedTime = setInterval(() => {
|
||||
// whether the video is buffering
|
||||
currentPlayPos = this.video.currentTime;
|
||||
currentPlayPos = this.video.currentTime();
|
||||
if (!bufferingDetected
|
||||
&& currentPlayPos < lastPlayPos + 0.01
|
||||
&& !this.video.paused) {
|
||||
&& !this.video.attr('paused')) {
|
||||
this.element.classList.add('dplayer-loading');
|
||||
bufferingDetected = true;
|
||||
}
|
||||
if (bufferingDetected
|
||||
&& currentPlayPos > lastPlayPos + 0.01
|
||||
&& !this.video.paused) {
|
||||
&& !this.video.attr('paused')) {
|
||||
this.element.classList.remove('dplayer-loading');
|
||||
bufferingDetected = false;
|
||||
}
|
||||
lastPlayPos = currentPlayPos;
|
||||
|
||||
this.updateBar('played', this.video.currentTime / this.video.duration, 'width');
|
||||
this.element.getElementsByClassName('dplayer-ptime')[0].innerHTML = secondToTime(this.video.currentTime);
|
||||
this.updateBar('played', this.video.currentTime() / this.video.duration, 'width');
|
||||
this.element.getElementsByClassName('dplayer-ptime')[0].innerHTML = utils.secondToTime(this.video.currentTime());
|
||||
this.trigger('playing');
|
||||
}, 100);
|
||||
if (this.option.danmaku && showdan) {
|
||||
danmakuTime = setInterval(() => {
|
||||
if (this.dan) {
|
||||
let item = this.dan[this.danIndex];
|
||||
while (item && this.video.currentTime > parseFloat(item.time)) {
|
||||
while (item && this.video.currentTime() > parseFloat(item.time)) {
|
||||
this.pushDanmaku(item.text, item.color, item.type);
|
||||
item = this.dan[++this.danIndex];
|
||||
}
|
||||
|
|
@ -250,16 +215,16 @@ class DPlayer {
|
|||
pbar.addEventListener('click', (event) => {
|
||||
const e = event || window.event;
|
||||
barWidth = pbar.clientWidth;
|
||||
let percentage = (e.clientX - getElementViewLeft(pbar)) / barWidth;
|
||||
let percentage = (e.clientX - utils.getElementViewLeft(pbar)) / barWidth;
|
||||
percentage = percentage > 0 ? percentage : 0;
|
||||
percentage = percentage < 1 ? percentage : 1;
|
||||
this.updateBar('played', percentage, 'width');
|
||||
this.video.currentTime = parseFloat(bar.playedBar.style.width) / 100 * this.video.duration;
|
||||
this.video.seek(parseFloat(bar.playedBar.style.width) / 100 * this.video.duration);
|
||||
});
|
||||
|
||||
this.isTipsShow = false;
|
||||
this.timeTipsHandler = this.timeTipsHandler(
|
||||
pbar, pbarTimeTips, secondToTime).bind(this);
|
||||
pbar, pbarTimeTips).bind(this);
|
||||
pbar.addEventListener('mousemove', this.timeTipsHandler);
|
||||
pbar.addEventListener('mouseover', this.timeTipsHandler);
|
||||
pbar.addEventListener('mouseenter', this.timeTipsHandler);
|
||||
|
|
@ -268,17 +233,17 @@ class DPlayer {
|
|||
|
||||
const thumbMove = (event) => {
|
||||
const e = event || window.event;
|
||||
let percentage = (e.clientX - getElementViewLeft(pbar)) / barWidth;
|
||||
let percentage = (e.clientX - utils.getElementViewLeft(pbar)) / barWidth;
|
||||
percentage = percentage > 0 ? percentage : 0;
|
||||
percentage = percentage < 1 ? percentage : 1;
|
||||
this.updateBar('played', percentage, 'width');
|
||||
this.element.getElementsByClassName('dplayer-ptime')[0].innerHTML = secondToTime(percentage * this.video.duration);
|
||||
this.element.getElementsByClassName('dplayer-ptime')[0].innerHTML = utils.secondToTime(percentage * this.video.duration);
|
||||
};
|
||||
|
||||
const thumbUp = () => {
|
||||
document.removeEventListener('mouseup', thumbUp);
|
||||
document.removeEventListener('mousemove', thumbMove);
|
||||
this.video.currentTime = parseFloat(bar.playedBar.style.width) / 100 * this.video.duration;
|
||||
this.video.seek(parseFloat(bar.playedBar.style.width) / 100 * this.video.duration);
|
||||
this.setTime();
|
||||
};
|
||||
|
||||
|
|
@ -302,10 +267,10 @@ class DPlayer {
|
|||
|
||||
this.switchVolumeIcon = () => {
|
||||
const volumeicon = this.element.getElementsByClassName('dplayer-volume-icon')[0];
|
||||
if (this.video.volume >= 0.8) {
|
||||
if (this.video.attr('volume') >= 0.8) {
|
||||
volumeicon.innerHTML = svg('volume-up');
|
||||
}
|
||||
else if (this.video.volume > 0) {
|
||||
else if (this.video.attr('volume') > 0) {
|
||||
volumeicon.innerHTML = svg('volume-down');
|
||||
}
|
||||
else {
|
||||
|
|
@ -314,7 +279,7 @@ class DPlayer {
|
|||
};
|
||||
const volumeMove = (event) => {
|
||||
const e = event || window.event;
|
||||
const percentage = (e.clientX - getElementViewLeft(volumeBarWrap) - 5.5) / vWidth;
|
||||
const percentage = (e.clientX - utils.getElementViewLeft(volumeBarWrap) - 5.5) / vWidth;
|
||||
this.volume(percentage);
|
||||
};
|
||||
const volumeUp = () => {
|
||||
|
|
@ -325,7 +290,7 @@ class DPlayer {
|
|||
|
||||
volumeBarWrapWrap.addEventListener('click', (event) => {
|
||||
const e = event || window.event;
|
||||
const percentage = (e.clientX - getElementViewLeft(volumeBarWrap) - 5.5) / vWidth;
|
||||
const percentage = (e.clientX - utils.getElementViewLeft(volumeBarWrap) - 5.5) / vWidth;
|
||||
this.volume(percentage);
|
||||
});
|
||||
volumeBarWrapWrap.addEventListener('mousedown', () => {
|
||||
|
|
@ -334,13 +299,13 @@ class DPlayer {
|
|||
volumeEle.classList.add('dplayer-volume-active');
|
||||
});
|
||||
volumeicon.addEventListener('click', () => {
|
||||
if (this.video.muted) {
|
||||
this.video.muted = false;
|
||||
if (this.video.attr('muted')) {
|
||||
this.video.attr('muted', false);
|
||||
this.switchVolumeIcon();
|
||||
this.updateBar('volume', this.video.volume, 'width');
|
||||
this.updateBar('volume', this.video.attr('volume'), 'width');
|
||||
}
|
||||
else {
|
||||
this.video.muted = true;
|
||||
this.video.attr('muted', true);
|
||||
volumeicon.innerHTML = svg('volume-off');
|
||||
this.updateBar('volume', 0, 'width');
|
||||
}
|
||||
|
|
@ -356,7 +321,7 @@ class DPlayer {
|
|||
this.element.classList.remove('dplayer-hide-controller');
|
||||
clearTimeout(hideTime);
|
||||
hideTime = setTimeout(() => {
|
||||
if (this.video.played.length) {
|
||||
if (this.video.attr('played').length) {
|
||||
this.element.classList.add('dplayer-hide-controller');
|
||||
closeSetting();
|
||||
closeComment();
|
||||
|
|
@ -417,11 +382,9 @@ class DPlayer {
|
|||
loopToggle.checked = !loopToggle.checked;
|
||||
if (loopToggle.checked) {
|
||||
loop = true;
|
||||
this.video.loop = loop;
|
||||
}
|
||||
else {
|
||||
loop = false;
|
||||
this.video.loop = loop;
|
||||
}
|
||||
closeSetting();
|
||||
});
|
||||
|
|
@ -438,7 +401,7 @@ class DPlayer {
|
|||
showdan = true;
|
||||
if (this.option.danmaku) {
|
||||
for (let i = 0; i < this.dan.length; i++) {
|
||||
if (this.dan[i].time >= this.video.currentTime) {
|
||||
if (this.dan[i].time >= this.video.currentTime()) {
|
||||
this.danIndex = i;
|
||||
break;
|
||||
}
|
||||
|
|
@ -446,7 +409,7 @@ class DPlayer {
|
|||
}
|
||||
danmakuTime = setInterval(() => {
|
||||
let item = this.dan[this.danIndex];
|
||||
while (item && this.video.currentTime >= parseFloat(item.time)) {
|
||||
while (item && this.video.currentTime() >= parseFloat(item.time)) {
|
||||
this.pushDanmaku(item.text, item.color, item.type);
|
||||
item = this.dan[++this.danIndex];
|
||||
}
|
||||
|
|
@ -478,7 +441,7 @@ class DPlayer {
|
|||
const speedItem = settingBox.getElementsByClassName('dplayer-setting-speed-item');
|
||||
for (let i = 0; i < speedItem.length; i++) {
|
||||
speedItem[i].addEventListener('click', () => {
|
||||
this.video.playbackRate = speedItem[i].dataset.speed;
|
||||
this.video.attr('playbackRate', speedItem[i].dataset.speed);
|
||||
closeSetting();
|
||||
});
|
||||
}
|
||||
|
|
@ -495,7 +458,7 @@ class DPlayer {
|
|||
|
||||
const danmakuMove = (event) => {
|
||||
const e = event || window.event;
|
||||
let percentage = (e.clientX - getElementViewLeft(danmakuBarWrap)) / dWidth;
|
||||
let percentage = (e.clientX - utils.getElementViewLeft(danmakuBarWrap)) / dWidth;
|
||||
percentage = percentage > 0 ? percentage : 0;
|
||||
percentage = percentage < 1 ? percentage : 1;
|
||||
this.updateBar('danmaku', percentage, 'width');
|
||||
|
|
@ -514,7 +477,7 @@ class DPlayer {
|
|||
|
||||
danmakuBarWrapWrap.addEventListener('click', (event) => {
|
||||
const e = event || window.event;
|
||||
let percentage = (e.clientX - getElementViewLeft(danmakuBarWrap)) / dWidth;
|
||||
let percentage = (e.clientX - utils.getElementViewLeft(danmakuBarWrap)) / dWidth;
|
||||
percentage = percentage > 0 ? percentage : 0;
|
||||
percentage = percentage < 1 ? percentage : 1;
|
||||
this.updateBar('danmaku', percentage, 'width');
|
||||
|
|
@ -539,61 +502,65 @@ class DPlayer {
|
|||
* video events
|
||||
*/
|
||||
// show video time: the metadata has loaded or changed
|
||||
this.video.addEventListener('durationchange', () => {
|
||||
if (this.video.duration !== 1) { // compatibility: Android browsers will output 1 at first
|
||||
this.element.getElementsByClassName('dplayer-dtime')[0].innerHTML = secondToTime(this.video.duration);
|
||||
this.video.on('all', 'durationchange', (i, video) => {
|
||||
if (video.duration !== 1) { // compatibility: Android browsers will output 1 at first
|
||||
this.element.getElementsByClassName('dplayer-dtime')[0].innerHTML = utils.secondToTime(this.video.duration);
|
||||
}
|
||||
});
|
||||
|
||||
// show video loaded bar: to inform interested parties of progress downloading the media
|
||||
this.video.addEventListener('progress', () => {
|
||||
const percentage = this.video.buffered.length ? this.video.buffered.end(this.video.buffered.length - 1) / this.video.duration : 0;
|
||||
this.video.on('current', 'progress', (i, video) => {
|
||||
const percentage = video.buffered.length ? video.buffered.end(video.buffered.length - 1) / video.duration : 0;
|
||||
this.updateBar('loaded', percentage, 'width');
|
||||
});
|
||||
|
||||
// video download error: an error occurs
|
||||
this.video.addEventListener('error', () => {
|
||||
this.video.on('all', 'error', () => {
|
||||
this.element.getElementsByClassName('dplayer-ptime')[0].innerHTML = `Error happens ╥﹏╥`;
|
||||
this.trigger('pause');
|
||||
});
|
||||
|
||||
// video can play: enough data is available that the media can be played
|
||||
this.video.addEventListener('canplay', () => {
|
||||
this.video.on('current', 'canplay', () => {
|
||||
this.trigger('canplay');
|
||||
});
|
||||
|
||||
// music end
|
||||
this.ended = false;
|
||||
this.video.addEventListener('ended', () => {
|
||||
this.updateBar('played', 1, 'width');
|
||||
if (!loop) {
|
||||
this.ended = true;
|
||||
this.pause();
|
||||
this.trigger('ended');
|
||||
this.video.on('all', 'ended', (i) => {
|
||||
if (i === this.video.videos.length - 1) {
|
||||
this.updateBar('played', 1, 'width');
|
||||
console.log(loop);
|
||||
if (!loop) {
|
||||
this.ended = true;
|
||||
this.pause();
|
||||
this.trigger('ended');
|
||||
}
|
||||
else {
|
||||
this.video.switch(0);
|
||||
this.video.play();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.video.addEventListener('play', () => {
|
||||
this.video.on('current', 'play', () => {
|
||||
if (this.paused) {
|
||||
this.play();
|
||||
}
|
||||
});
|
||||
|
||||
this.video.addEventListener('pause', () => {
|
||||
this.video.on('current', 'pause', () => {
|
||||
if (!this.paused) {
|
||||
this.pause();
|
||||
}
|
||||
});
|
||||
|
||||
// control volume
|
||||
this.video.volume = parseInt(this.element.getElementsByClassName('dplayer-volume-bar-inner')[0].style.width) / 100;
|
||||
|
||||
// loop
|
||||
this.video.loop = loop;
|
||||
this.video.attr('volume', parseInt(this.element.getElementsByClassName('dplayer-volume-bar-inner')[0].style.width) / 100);
|
||||
|
||||
// set duration time
|
||||
if (this.video.duration !== 1) { // compatibility: Android browsers will output 1 at first
|
||||
this.element.getElementsByClassName('dplayer-dtime')[0].innerHTML = this.video.duration ? secondToTime(this.video.duration) : '00:00';
|
||||
this.element.getElementsByClassName('dplayer-dtime')[0].innerHTML = this.video.duration ? utils.secondToTime(this.video.duration) : '00:00';
|
||||
}
|
||||
|
||||
// danmaku
|
||||
|
|
@ -650,7 +617,7 @@ class DPlayer {
|
|||
token: this.option.danmaku.token,
|
||||
player: this.option.danmaku.id,
|
||||
author: this.option.danmaku.user,
|
||||
time: this.video.currentTime,
|
||||
time: this.video.currentTime(),
|
||||
text: commentInput.value,
|
||||
color: this.element.querySelector('.dplayer-comment-setting-color input:checked').value,
|
||||
type: this.element.querySelector('.dplayer-comment-setting-type input:checked').value
|
||||
|
|
@ -774,8 +741,8 @@ class DPlayer {
|
|||
else if (this.element.webkitRequestFullscreen) {
|
||||
this.element.webkitRequestFullscreen();
|
||||
}
|
||||
else if (this.video.webkitEnterFullscreen) { // Safari for iOS
|
||||
this.video.webkitEnterFullscreen();
|
||||
else if (this.video.attr('webkitEnterFullscreen')) { // Safari for iOS
|
||||
this.video.current.webkitEnterFullscreen();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -818,20 +785,20 @@ class DPlayer {
|
|||
break;
|
||||
case 37:
|
||||
event.preventDefault();
|
||||
this.video.currentTime = this.video.currentTime - 5;
|
||||
this.video.seek(this.video.currentTime() - 5);
|
||||
break;
|
||||
case 39:
|
||||
event.preventDefault();
|
||||
this.video.currentTime = this.video.currentTime + 5;
|
||||
this.video.seek(this.video.currentTime() + 5);
|
||||
break;
|
||||
case 38:
|
||||
event.preventDefault();
|
||||
percentage = this.video.volume + 0.1;
|
||||
percentage = this.video.attr('volume') + 0.1;
|
||||
this.volume(percentage);
|
||||
break;
|
||||
case 40:
|
||||
event.preventDefault();
|
||||
percentage = this.video.volume - 0.1;
|
||||
percentage = this.video.attr('volume') - 0.1;
|
||||
this.volume(percentage);
|
||||
break;
|
||||
}
|
||||
|
|
@ -896,9 +863,9 @@ class DPlayer {
|
|||
const camareIcon = this.element.getElementsByClassName('dplayer-camera-icon')[0];
|
||||
camareIcon.addEventListener('click', () => {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = this.video.videoWidth;
|
||||
canvas.height = this.video.videoHeight;
|
||||
canvas.getContext('2d').drawImage(this.video, 0, 0, canvas.width, canvas.height);
|
||||
canvas.width = this.video.attr('videoWidth');
|
||||
canvas.height = this.video.attr('videoHeight');
|
||||
canvas.getContext('2d').drawImage(this.video.current, 0, 0, canvas.width, canvas.height);
|
||||
|
||||
camareIcon.href = canvas.toDataURL();
|
||||
camareIcon.download = "DPlayer.png";
|
||||
|
|
@ -913,10 +880,10 @@ class DPlayer {
|
|||
*/
|
||||
play (time) {
|
||||
if (Object.prototype.toString.call(time) === '[object Number]') {
|
||||
this.video.currentTime = time;
|
||||
this.video.seek(time);
|
||||
}
|
||||
this.paused = false;
|
||||
if (this.video.paused) {
|
||||
if (this.video.attr('paused')) {
|
||||
this.bezel.innerHTML = svg('play');
|
||||
this.bezel.classList.add('dplayer-bezel-transition');
|
||||
}
|
||||
|
|
@ -939,7 +906,7 @@ class DPlayer {
|
|||
this.paused = true;
|
||||
this.element.classList.remove('dplayer-loading');
|
||||
|
||||
if (!this.video.paused) {
|
||||
if (!this.video.attr('paused')) {
|
||||
this.bezel.innerHTML = svg('pause');
|
||||
this.bezel.classList.add('dplayer-bezel-transition');
|
||||
}
|
||||
|
|
@ -959,9 +926,9 @@ class DPlayer {
|
|||
percentage = percentage > 0 ? percentage : 0;
|
||||
percentage = percentage < 1 ? percentage : 1;
|
||||
this.updateBar('volume', percentage, 'width');
|
||||
this.video.volume = percentage;
|
||||
if (this.video.muted) {
|
||||
this.video.muted = false;
|
||||
this.video.attr('volume', percentage);
|
||||
if (this.video.attr('muted')) {
|
||||
this.video.attr('muted', false);
|
||||
}
|
||||
this.switchVolumeIcon();
|
||||
}
|
||||
|
|
@ -970,7 +937,7 @@ class DPlayer {
|
|||
* Toggle between play and pause
|
||||
*/
|
||||
toggle () {
|
||||
if (this.video.paused) {
|
||||
if (this.video.attr('paused')) {
|
||||
this.play();
|
||||
}
|
||||
else {
|
||||
|
|
@ -981,9 +948,9 @@ class DPlayer {
|
|||
/**
|
||||
* attach event
|
||||
*/
|
||||
on (name, func) {
|
||||
if (typeof func === 'function') {
|
||||
this.event[name].push(func);
|
||||
on (event, callback) {
|
||||
if (typeof callback === 'function') {
|
||||
this.event[event].push(callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1147,6 +1114,7 @@ class DPlayer {
|
|||
* @param {Object} video - new video info
|
||||
* @param {Object} danmaku - new danmaku info
|
||||
*/
|
||||
// TODO
|
||||
switchVideo (video, danmaku) {
|
||||
this.video.src = video.url;
|
||||
this.video.poster = video.pic ? video.pic : '';
|
||||
|
|
@ -1171,7 +1139,7 @@ class DPlayer {
|
|||
}
|
||||
}
|
||||
|
||||
timeTipsHandler (pbar, timeTips, secondToTime) {
|
||||
timeTipsHandler (pbar, timeTips) {
|
||||
// http://stackoverflow.com/questions/1480133/how-can-i-get-an-objects-absolute-position-on-the-page-in-javascript
|
||||
const cumulativeOffset = (element) => {
|
||||
let top = 0, left = 0;
|
||||
|
|
@ -1194,7 +1162,7 @@ class DPlayer {
|
|||
const { clientX } = e;
|
||||
const px = cumulativeOffset(pbar).left;
|
||||
const tx = clientX - px;
|
||||
timeTips.innerText = secondToTime(this.video.duration * (tx / pbar.offsetWidth));
|
||||
timeTips.innerText = utils.secondToTime(this.video.duration * (tx / pbar.offsetWidth));
|
||||
timeTips.style.left = `${(tx - 20)}px`;
|
||||
switch (e.type) {
|
||||
case 'mouseenter':
|
||||
|
|
|
|||
|
|
@ -161,6 +161,11 @@
|
|||
.dplayer-video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dplayer-video-current {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
13
src/html.js
13
src/html.js
|
|
@ -1,10 +1,15 @@
|
|||
const svg = require('./svg.js');
|
||||
|
||||
module.exports = {
|
||||
main: (option, index, tran) => `
|
||||
main: (option, index, tran) => {
|
||||
let videos = ``;
|
||||
for (let i = 0; i < option.video.url.length; i++) {
|
||||
videos += `<video class="dplayer-video ${i === 0 ? `dplayer-video-current"` : ``}" ${option.video.pic ? `poster="${option.video.pic}"` : ``} webkit-playsinline playsinline ${option.screenshot ? `crossorigin="anonymous"` : ``} preload="${option.video.url.length ? 'metadata' : option.preload}" src="${option.video.url[i]}"></video>`;
|
||||
}
|
||||
return `
|
||||
<div class="dplayer-mask"></div>
|
||||
<div class="dplayer-video-wrap">
|
||||
<video class="dplayer-video" ${option.video.pic ? `poster="${option.video.pic}"` : ``} webkit-playsinline playsinline ${option.screenshot ? `crossorigin="anonymous"` : ``} preload="${option.preload}" src="${option.video.url}"></video>
|
||||
${videos}
|
||||
<div class="dplayer-danmaku">
|
||||
<div class="dplayer-danmaku-item dplayer-danmaku-item--demo"></div>
|
||||
</div>
|
||||
|
|
@ -154,8 +159,8 @@ module.exports = {
|
|||
<div class="dplayer-menu-item"><span class="dplayer-menu-label"><a target="_blank" href="http://diygod.me/">${tran('About author')}</a></span></div>
|
||||
<div class="dplayer-menu-item"><span class="dplayer-menu-label"><a target="_blank" href="https://github.com/DIYgod/DPlayer/issues">${tran('DPlayer feedback')}</a></span></div>
|
||||
<div class="dplayer-menu-item"><span class="dplayer-menu-label"><a target="_blank" href="https://github.com/DIYgod/DPlayer">${tran('About DPlayer')}</a></span></div>
|
||||
</div>
|
||||
`,
|
||||
</div>`;
|
||||
},
|
||||
|
||||
setting: (tran) => ({
|
||||
'original': `
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ module.exports = (option) => {
|
|||
option[defaultKey] = defaultOption[defaultKey];
|
||||
}
|
||||
}
|
||||
if (Object.prototype.toString.call(option.video.url) !== '[object Array]') {
|
||||
option.video.url = [option.video.url];
|
||||
}
|
||||
if (option.video && !option.video.hasOwnProperty('type')) {
|
||||
option.video.type = 'auto';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
module.exports = {
|
||||
|
||||
/**
|
||||
* Parse second to 00:00 format
|
||||
*
|
||||
* @param {Number} second
|
||||
* @return {String} 00:00 format
|
||||
*/
|
||||
secondToTime: (second) => {
|
||||
const add0 = (num) => num < 10 ? '0' + num : '' + num;
|
||||
const min = parseInt(second / 60);
|
||||
const sec = parseInt(second - min * 60);
|
||||
return add0(min) + ':' + add0(sec);
|
||||
},
|
||||
|
||||
/**
|
||||
* control play progress
|
||||
*/
|
||||
// get element's view position
|
||||
getElementViewLeft: (element) => {
|
||||
let actualLeft = element.offsetLeft;
|
||||
let current = element.offsetParent;
|
||||
const elementScrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft;
|
||||
if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement) {
|
||||
while (current !== null) {
|
||||
actualLeft += current.offsetLeft;
|
||||
current = current.offsetParent;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (current !== null && current !== this.element) {
|
||||
actualLeft += current.offsetLeft;
|
||||
current = current.offsetParent;
|
||||
}
|
||||
}
|
||||
return actualLeft - elementScrollLeft;
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
class Video {
|
||||
constructor (videos) {
|
||||
this.videos = videos;
|
||||
this.multi = this.videos.length > 1;
|
||||
this.index = 0;
|
||||
this.current = this.videos[this.index];
|
||||
|
||||
this.duration = 0;
|
||||
this.durationArr = [];
|
||||
this.eventAll = [];
|
||||
this.eventCurrent = [];
|
||||
|
||||
this.on('all', 'durationchange', (i, video) => {
|
||||
if (video.duration !== 1) { // some Android browsers will output 1 at first
|
||||
this.durationArr[i] = video.duration;
|
||||
this.duration = this.durationArr.reduce((sum, cur) => sum + cur);
|
||||
}
|
||||
});
|
||||
this.on('current', 'end', () => {
|
||||
this.switch(this.index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
switch (index, time) {
|
||||
if (this.index !== index) {
|
||||
this.videos[index].classList.add('dplayer-video-current');
|
||||
if (!this.current.paused) {
|
||||
this.videos[index].play();
|
||||
}
|
||||
this.current.classList.remove('dplayer-video-current');
|
||||
this.current.pause();
|
||||
|
||||
this.index = index;
|
||||
this.current = this.videos[this.index];
|
||||
this.videos[index].currentTime = time ? time : 0;
|
||||
}
|
||||
else {
|
||||
this.videos[index].currentTime = time ? time : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// bind event
|
||||
on (type, event, callback) {
|
||||
if (typeof callback === 'function') {
|
||||
if (type === 'all') {
|
||||
if (!this.eventAll[event]) {
|
||||
this.eventAll[event] = [];
|
||||
}
|
||||
this.eventAll[event].push(callback);
|
||||
}
|
||||
else {
|
||||
if (!this.eventCurrent[event]) {
|
||||
this.eventCurrent[event] = [];
|
||||
}
|
||||
this.eventCurrent[event].push(callback);
|
||||
}
|
||||
|
||||
if (['seeking'].indexOf(event) === -1) {
|
||||
for (let i = 0; i < this.videos.length; i++) {
|
||||
this.videos[i].addEventListener(event, () => {
|
||||
if (type === 'all' || this.videos[i] === this.current) {
|
||||
callback(i, this.videos[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// trigger event
|
||||
trigger (type, event) {
|
||||
const events = type === 'all' ? this.eventAll : this.eventCurrent;
|
||||
for (let i = 0; i < events[event].length; i++) {
|
||||
events[event][i]();
|
||||
}
|
||||
}
|
||||
|
||||
currentTime () {
|
||||
if (this.durationArr.slice(0, this.index).length) {
|
||||
return this.durationArr.slice(0, this.index).reduce((sum, cur) => sum + cur) + this.current.currentTime;
|
||||
}
|
||||
else {
|
||||
return this.current.currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
seek (time) {
|
||||
time = Math.max(time, 0);
|
||||
time = Math.min(time, this.duration);
|
||||
|
||||
let i = 0;
|
||||
let tmptime = 0;
|
||||
while (tmptime <= time) {
|
||||
tmptime += this.durationArr[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
let currentTime;
|
||||
if (this.durationArr.slice(0, this.index).length) {
|
||||
currentTime = time - this.durationArr.slice(0, i - 1).reduce((sum, cur) => sum + cur);
|
||||
}
|
||||
else {
|
||||
currentTime = time;
|
||||
}
|
||||
|
||||
this.switch(i - 1, currentTime);
|
||||
|
||||
this.trigger('all', 'seeking');
|
||||
}
|
||||
|
||||
attr (option, value) {
|
||||
if (value !== undefined) {
|
||||
for (let i = 0; i < this.videos.length; i++) {
|
||||
this.videos[i][option] = value;
|
||||
}
|
||||
}
|
||||
return this.current[option];
|
||||
}
|
||||
|
||||
play () {
|
||||
this.current.play();
|
||||
}
|
||||
|
||||
pause () {
|
||||
this.current.pause();
|
||||
}
|
||||
|
||||
toggle () {
|
||||
this.current.paused ? this.play() : this.pause();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Video;
|
||||
Loading…
Reference in New Issue