Javascript Video Custom Controls

JavaScript를 활용한 HTML5 Video 네이티브 커스텀 컨트롤 만들기

커스텀 컨트롤을 만들기 위해서는 우선 브라우저에서 자체 제공하는 네이티브 컨트롤을 감춰야 한다.
Video 엘리먼트의 속성중 controls에 false 값을 주면 브라우저가 알아서 네이티브 컨트롤을 숨길수 있다.(controls 속성은 default 값이 false이기 때문에 아예 속성을 지정 안해도 무관하다.)
네이티브 컨트롤을 감춘 후 커스텀 컨트롤을 추가해서 제어하면 된다.

HTML 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="videoContainer" class="video_container">
<video id="video">
<source src="http://content.bitsontherun.com/videos/q1fx20VZ-27m5HpIu.webm" type="video/webm">
<source src="http://content.bitsontherun.com/videos/q1fx20VZ-52qL9xLP.mp4" type="video/mp4">
</video>
<div id="videoControls" class="video_controls">
<div class="group">
<button type="button" id="btnRestart">Re</button>
<button type="button" id="btnRew">&lt;&lt;</button>
<button type="button" id="btnPlay" class="play">Play</button>
<button type="button" id="btnFastFwd">&gt;&gt;</button>
<input type="range" value="0" id="seekBar" class="seek_bar">
<button type="button" id="btnMute">Mute</button>
<input type="range" min="0" max="1" step="0.1" value="1" id="volumeBar" class="volume_bar">
<button type="button" id="btnVolUp">Vol Up</button>
<button type="button" id="btnVolDown">Vol Down</button>
<button type="button" id="btnFullScreen">Full Screen</button>
</div>
</div>
</div>

CSS 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
* {
margin: 0;
padding: 0;
}

.video_container {
overflow: hidden;
position: relative;
background-color: #000;
width: 640px;
height: 365px;
}

.video_container video {
width: 100%;
height: 100%;
}

.video_container video::-webkit-media-controls {
display:none !important;
}
.video_container video::-webkit-media-controls-enclosure {
display:none !important;
}

.video_container .video_controls {
position: absolute;
right: 0;
bottom: 0;
left: 0;
/*z-index: 2147483647;*/
padding: 5px;
opacity: 1;
-webkit-transition: opacity .3s;
-moz-transition: opacity .3s;
-o-transition: opacity .3s;
-ms-transition: opacity .3s;
transition: opacity .3s;
background-image: linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -o-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -moz-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -webkit-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -ms-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.13, rgb(3,113,168)), color-stop(1, rgb(0,136,204)));
text-align: center;
}

.video_container .video_controls>.group {
display: inline-block;
}

.video_container .video_controls button[type=button] {
padding: 4px;
background: rgba(0,0,0,.5);
border: 0;
border-radius: 3px;
color: #eee;
vertical-align: top;
cursor: pointer;
}

.video_container .video_controls .seek_bar {
width: 200px;
}

.video_container .video_controls .volume_bar {
width: 40px;
}

JavaScript 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
var $video = document.querySelector("#video");

/**
* videoPlay
* @description 비디오 영상 플레이/정지
*/
function videoPlay() {
if ($video.paused) {
$video.currentTime = parseInt($video.duration * (this.value / 100), 10);
$video.play();
} else {
$video.pause();
}
}

/**
* skip
* @description 비디오 영상 앞/뒤 스킵
* @param {Number} value - 비디오 재생 타임 시간
*/
function skip(value) {
if ($video.paused) { return; }

$video.currentTime += value;
}

/**
* setVolume
* @description 볼륨 조절
* @param {Number} value - 볼륨 조절 값(min: 0 ~ max: 1)
*/
function setVolume(value) {
var vol = $video.volume;

vol += value;

if (vol >= 0 && vol <= 1) {
$video.volume = vol;
} else {
$video.volume = (vol < 0)? 0 : 1;
}
}

// 진행바 업데이트 이동 이벤트
$video.addEventListener('timeupdate', function() {
if ($video.paused) { return; }

document.querySelector('#seekBar').value = (100 / $video.duration) * $video.currentTime;
});

// 재시작 버튼 클릭 이벤트 핸들러
document.querySelector('#btnRestart').addEventListener('click', function() {
$video.currentTime = 0;
});

// 플레이 버튼 클릭 이벤트 핸들러
document.querySelector('#btnPlay').addEventListener('click', videoPlay);

// 재시작 버튼 클릭 이벤트 핸들러1
document.querySelector('#btnRew').addEventListener('click', function() {
skip(-10);
});

// 재시작 버튼 클릭 이벤트 핸들러2
document.querySelector('#btnFastFwd').addEventListener('click', function() {
skip(10);
});

// 진행바 마우스다운 이벤트 핸들러
document.querySelector('#seekBar').addEventListener('mousedown', function(e) {
$video.pause();
});

// 진행바 마우스업 이벤트 핸들러
document.querySelector('#seekBar').addEventListener('mouseup', videoPlay);

// muted 속성 사운드트랙 음소거 제어
document.querySelector('#btnMute').addEventListener('click', function (e) {
if ($video.muted) {
$video.muted = false;
} else {
$video.muted = true;
}
}, false);

// 볼륨 range 컨트롤
document.querySelector('#volumeBar').addEventListener('change', function () {
$video.volume = this.value;
}, false);

// 볼륨 버튼 컨트롤
document.querySelector('#btnVolUp').addEventListener("click", function () {
setVolume(.1); // up by 10%
}, false);

document.querySelector('#btnVolDown').addEventListener("click", function () {
setVolume(-.1); // down by 10%
}, false);

// FullScreen 클릭 이벤트 핸들러
document.querySelector('#btnFullScreen').addEventListener('click', function() {
var $videoContainer = document.querySelector('#videoContainer');

if ($videoContainer.requestFullscreen) {
$videoContainer.requestFullscreen();
} else if ($videoContainer.mozRequestFullScreen) {
$videoContainer.mozRequestFullScreen();
} else if ($videoContainer.webkitRequestFullscreen) {
$videoContainer.webkitRequestFullscreen();
} else if($videoContainer.msRequestFullscreen){
$videoContainer.msRequestFullscreen();
}

$videoContainer.style.width = '100%';
$videoContainer.style.height = '100%';
});

// FullScreen 상태를 해제 시 원래 사이즈로 복원
document.addEventListener('webkitfullscreenchange', function() { // Webkit
var $videoContainer = document.querySelector('#videoContainer');

if (!document.webkitIsFullScreen) {
$videoContainer.style.width = '640px';
$videoContainer.style.height = '365px';
}
});

document.addEventListener('mozfullscreenchange', function() { // Firefox
if (!document.mozIsFullScreen) {
videoContainer.style.width = '640px';
videoContainer.style.height = '365px';
}
});

document.addEventListener('MSFullscreenChange', function() { // Explorer
if (!document.msFullscreenElement) {
videoContainer.style.width = '640px';
videoContainer.style.height = '365px';
}
});

참조

공유하기