Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit accaf0e

Browse files
day 13
1 parent ab3103f commit accaf0e

File tree

12 files changed

+496
-1
lines changed

12 files changed

+496
-1
lines changed

‎README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
## Code Today!
1515

16-
Motivate yourself to code daily till 60 days, and see the magic!
16+
Motivate yourself to code daily till 30 days, and see the magic!
1717

1818
| Day | Topic | Link | Summary |
1919
| ---------- | ----- | ------------ | ---------: |
@@ -29,3 +29,4 @@ Motivate yourself to code daily till 60 days, and see the magic!
2929
| [Day 10](./each%20day%20build%20day!/Day%2010/) | [Infinite scrolling ComicBook](./each%20day%20build%20day!/Day%2010/) | [demo]() | [Takeaways](./each%20day%20build%20day!/Day%2010/README.md/) |
3030
| [Day 11](./each%20day%20build%20day!/Day%11/) | [Drag & Drop File Upload](./each%20day%20build%20day!/Day%2011/) | [demo]() | [Takeaways](./each%20day%20build%20day!/Day%2011/README.md/) |
3131
| [Day 12](./each%20day%20build%20day!/Day%12/) | [Multi select checkboxes](./each%20day%20build%20day!/Day%2012/) | [demo]() | [Takeaways](./each%20day%20build%20day!/Day%2012/README.md/) |
32+
| [Day 13](./each%20day%20build%20day!/Day%13/) | [Custom video player](./each%20day%20build%20day!/Day%2013/) | [demo]() | [Takeaways](./each%20day%20build%20day!/Day%2013/README.md/) |
30.9 MB
Binary file not shown.

‎each day build day!/day 13/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Custom video player
2+
3+
The default html video player has limited capabilities also its different for different browsers.
4+
So, I decided built a custom one with some of the important features like `play pause` on click over the video, `volume control`, `playback control`, `full screen mode`, `skip`, `scrub` etc all this using plain javascript and css.
5+
6+
# Challenges
7+
- video element
8+
- video properties
9+
- progress bar
10+
- scrubbing
11+
- skipping
12+
- css
13+
14+
15+
16+
# demo
17+
![demo picture](demo.png)
18+
![full screen mode](full.png)
Lines changed: 15 additions & 0 deletions
Loading[フレーム]

‎each day build day!/day 13/demo.png

192 KB
Loading[フレーム]

‎each day build day!/day 13/full.png

385 KB
Loading[フレーム]
Lines changed: 50 additions & 0 deletions
Loading[フレーム]

‎each day build day!/day 13/index.html

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Custom video player</title>
7+
<link rel="stylesheet" href="style.css">
8+
<script defer src="main.js"></script>
9+
</head>
10+
<body>
11+
<div class="container">
12+
<h1>Custom video player using vanilla JS</h1>
13+
<div class="player">
14+
<video class="player__video viewer" src="Funny Birds Animated Short Film.mp4"></video>
15+
16+
<div class="player__controls">
17+
<div class="progress">
18+
<div class="progress__filled"></div>
19+
</div>
20+
<button class="player__button toggle" title="Toggle Play"></button>
21+
<input type="range" name="volume" class="player__slider" min="0" max="1" step="0.05" value="1">
22+
<div class="player__button unmute" id="mute"></div>
23+
<input type="range" name="playbackRate" class="player__slider" min="0.5" max="2" step="0.1" value="1">
24+
<button data-skip="-10" class="player__button">« 10s</button>
25+
<button data-skip="25" class="player__button">25s »</button>
26+
<div class="player__button zoom"></div>
27+
</div>
28+
</div>
29+
30+
31+
</body>
32+
</html>

‎each day build day!/day 13/issues.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Bugs :
2+
- progressbar isn't working
3+
- unresponsiveness
4+
- bad icons
5+
- full-screen no control on hover
6+
- no feedback for keyboard keys like space, right, left,

‎each day build day!/day 13/main.js

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//get hold of each element
2+
const player = document.querySelector('.player');
3+
const viewer = player.querySelector('.viewer')
4+
const toggle = player.querySelector('.toggle')
5+
//anything with data-skip
6+
const skipButtons = player.querySelectorAll('[data-skip]');
7+
const mute = player.querySelector('#mute');
8+
const progress = player.querySelector('.progress');
9+
const progressBar = player.querySelector('.progress__filled');
10+
const ranges = player.querySelectorAll('.player__slider');
11+
const fullscreen = player.querySelector('.zoom');
12+
13+
14+
//functions
15+
function togglePlay(){
16+
const status = viewer.paused ? 'play':'pause';
17+
viewer[status]();
18+
}
19+
20+
function toggleButton(){
21+
const icon = this.paused ? '►' : '❚ ❚';
22+
toggle.textContent = icon;
23+
24+
}
25+
26+
function skip() {
27+
viewer.currentTime += parseFloat(this.dataset.skip);
28+
}
29+
30+
function handleVolumeAndPlayback(){
31+
//name will be either 'volume', 'playbackrate'
32+
viewer[this.name] = this.value;
33+
}
34+
35+
function toggleMute(){
36+
viewer.muted =!viewer.muted;
37+
if(mute.classList.contains('unmute')){
38+
mute.classList.remove('unmute')
39+
mute.classList.add('mute')
40+
}
41+
42+
43+
if(mute.classList.contains('mute')){
44+
mute.classList.remove('mute')
45+
mute.classList.add('unmute')
46+
}
47+
}
48+
49+
function handleProgress(){
50+
//change the flex-basis based on the width or the played/duration
51+
const currentWidth = (viewer.currentTime / viewer.duration) * 100 || 0;
52+
progressBar.style.flexBasis = `${currentWidth}%`
53+
}
54+
55+
function scrub(e){
56+
const scrubTime = (e.offsetX / progress.offsetWidth) * viewer.duration;
57+
viewer.currentTime = scrubTime;
58+
}
59+
60+
function handleFullscreen(e){
61+
if (isFullScreen()) {
62+
if (document.exitFullscreen) document.exitFullscreen();
63+
else if (document.mozCancelFullScreen) document.mozCancelFullScreen();
64+
else if (document.webkitCancelFullScreen) document.webkitCancelFullScreen();
65+
else if (document.msExitFullscreen) document.msExitFullscreen();
66+
setFullscreenData(false);
67+
}
68+
else {
69+
if (viewer.requestFullscreen) viewer.requestFullscreen();
70+
else if (viewer.mozRequestFullScreen) viewer.mozRequestFullScreen();
71+
else if (viewer.webkitRequestFullScreen) viewer.webkitRequestFullScreen();
72+
else if (viewer.msRequestFullscreen) viewer.msRequestFullscreen();
73+
setFullscreenData(true);
74+
}
75+
}
76+
77+
const setFullscreenData = function(state) {
78+
viewer.setAttribute('data-fullscreen', !!state);
79+
}
80+
81+
//check if fullscreenApi is supported
82+
const fullScreenEnabled = !!(document.fullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled || document.webkitSupportsFullscreen || document.webkitFullscreenEnabled || document.createElement('video').webkitRequestFullScreen);
83+
if (!fullScreenEnabled) {
84+
fullscreen.style.display = 'none';
85+
}
86+
87+
//check status if fullscreen
88+
const isFullScreen = function() {
89+
return !!(document.fullScreen || document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement || document.fullscreenElement);
90+
}
91+
92+
93+
//event listeners
94+
viewer.addEventListener('click', togglePlay);
95+
viewer.addEventListener('play', toggleButton);
96+
viewer.addEventListener('pause', toggleButton);
97+
viewer.addEventListener('timeupdate', handleProgress)
98+
99+
toggle.addEventListener('click', togglePlay)
100+
mute.addEventListener('click',toggleMute)
101+
skipButtons.forEach(button => button.addEventListener('click', skip));
102+
103+
ranges.forEach(range => range.addEventListener('change',handleVolumeAndPlayback));
104+
ranges.forEach(range => range.addEventListener('mousemove',handleVolumeAndPlayback));
105+
106+
progress.addEventListener('click', scrub)
107+
108+
let mousedownFlag = false;
109+
progress.addEventListener('mousedown', ()=> mousedownFlag = true)
110+
progress.addEventListener('mouseup', ()=> mousedownFlag = false)
111+
//listen to mousemove only when user has clicked the left mouse button
112+
progress.addEventListener('mousemove', (e)=> mousedownFlag && scrub(e))
113+
fullscreen.addEventListener('click', handleFullscreen)
114+
115+
// fullscreen events
116+
document.addEventListener('fullscreenchange', function(e) {
117+
setFullscreenData(!!(document.fullScreen || document.fullscreenElement));
118+
});
119+
document.addEventListener('webkitfullscreenchange', function() {
120+
setFullscreenData(!!document.webkitIsFullScreen);
121+
});
122+
document.addEventListener('mozfullscreenchange', function() {
123+
setFullscreenData(!!document.mozFullScreen);
124+
});
125+
document.addEventListener('msfullscreenchange', function() {
126+
setFullscreenData(!!document.msFullscreenElement);
127+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /