JS 비디오 제어 · watchPosition 완전 정리
자바스크립트 비디오 제어와 watchPosition 반복 위치 서비스를 한 흐름으로 정리합니다.
<video id="video" width="320" height="240">
<source src="media/bear.mp4" type="video/mp4">
</video>
<button id="play" onclick="control(event)">play</button>
<script>
let video = document.getElementById("video");
function control(e) {
if (e.target.id == "play") video.play();
else if (e.target.id == "pause") video.pause();
else if (e.target.id == "replay") { video.load(); video.play(); }
else if (e.target.id == "vol-") video.volume -= 0.1;
else if (e.target.id == "vol+") video.volume += 0.1;
else if (e.target.id == "mute on/off") video.muted = !video.muted;
}
let options = { enableHighAccuracy: false, timeout: 5000, maximumAge: 0 };
let watchID = navigator.geolocation.watchPosition(changed, null, options);
function changed(position) {
let lat = position.coords.latitude;
let lon = position.coords.longitude;
map.src = "https://www.openstreetmap.org/export/embed.html?bbox=" +
(parseFloat(lon)-0.01) + "%2C" + (parseFloat(lat)-0.01) + "%2C" +
(parseFloat(lon)+0.01) + "%2C" + (parseFloat(lat)+0.01);
}
</script>
92번 폴더는 비디오를 자바스크립트로 제어하는 예제와 watchPosition으로 위치 변화를 반복 감지하는 예제를 함께 다룹니다. 둘 다 브라우저 객체를 가져와 메서드와 이벤트성 콜백으로 상태를 바꾸는 구조입니다.
- 비디오는 video 요소의 play, pause, load, volume, muted를 제어합니다.
- 위치는 navigator.geolocation.watchPosition으로 반복 콜백을 받습니다.
- 두 예제 모두 버튼, 메시지 영역, 상태 변수가 중요합니다.
- 파일 경로와 보안 환경이 동작 여부에 큰 영향을 줍니다.
video 태그는 id, width, height를 가지고 있고 내부 source 태그가 실제 mp4 파일을 가리킵니다. 스크립트에서는 getElementById로 video 요소를 가져온 뒤 제어합니다.
| 요소 | 역할 | 주의 |
|---|---|---|
| video | 재생 대상 | id가 스크립트와 같아야 합니다. |
| source | 파일 경로 제공 | type을 video/mp4로 지정합니다. |
| msg | 상태 메시지 출력 | innerHTML로 갱신합니다. |
| button | 제어 명령 실행 | id로 분기합니다. |
control 함수는 e.target.id를 읽어 어떤 버튼이 눌렸는지 판단합니다. 버튼이 늘어날수록 if/else가 길어지므로, 실전에서는 id와 함수를 매핑하는 객체로 정리할 수도 있습니다.
- 클릭 이벤트가 control(event)를 호출합니다.
- e.target.id로 버튼 id를 읽습니다.
- id가 play, pause, replay, vol-, vol+, mute on/off 중 무엇인지 비교합니다.
- 해당하는 video 메서드나 속성을 실행합니다.
play는 재생, pause는 일시정지, replay는 다시 로드 후 재생입니다. replay에서 load를 쓰면 source를 다시 읽고 처음부터 시작하는 효과가 있습니다.
| 버튼 | 실행 | 메시지 |
|---|---|---|
| play | video.play() | 파일을 재생중입니다. |
| pause | video.pause() | 일시중지되었습니다. |
| replay | video.load(); video.play() | 처음부터 다시 재생합니다. |
| currentTime 방식 | video.currentTime = 0 | 더 가벼운 되감기 방식입니다. |
video.volume은 0 이상 1 이하 값이고, muted는 true/false 값입니다. 원문은 볼륨을 0.1씩 증감하고, 음소거는 현재 값을 반대로 바꿉니다.
- volume이 0.1 이하이면 0으로 보정합니다.
- volume이 0.9 이상이면 1.0으로 보정합니다.
- muted는 볼륨 값을 유지한 채 출력만 막습니다.
- UI에는 현재 볼륨과 음소거 상태를 메시지로 보여 줍니다.
video.src는 source 태그를 사용한 구조에서 기대한 값을 바로 주지 않을 수 있습니다. 원문은 video의 자식 요소를 순회해 SOURCE 태그의 src를 찾아 반환합니다.
function getSource(v) {
let child = v.firstElementChild;
for (let i = 0; i < v.childElementCount; i++) {
if (child.tagName == "SOURCE") return child.src;
child = child.nextElementSibling;
}
return "";
}
watchPosition은 현재 위치를 한 번만 받는 getCurrentPosition과 달리 위치가 바뀔 때마다 콜백을 반복 호출합니다. 반환값 watchID는 나중에 clearWatch로 중지할 때 사용합니다.
| API | 역할 |
|---|---|
| watchPosition(changed, null, options) | 위치 변화 감시 시작 |
| changed(position) | 변경된 위치 처리 |
| clearWatch(watchID) | 반복 감시 종료 |
| options | 정확도, 시간 제한, 캐시 조건 설정 |
options는 위치 요청의 동작 방식을 제어합니다. 원문은 높은 정확도는 끄고, 5초 timeout과 maximumAge 0을 설정했습니다.
| 옵션 | 값 | 의미 |
|---|---|---|
| enableHighAccuracy | false | 고정밀 위치를 강제하지 않습니다. |
| timeout | 5000 | 5초 안에 응답이 없으면 실패합니다. |
| maximumAge | 0 | 캐시된 위치를 사용하지 않습니다. |
| error 콜백 | null | 원문은 실패 처리를 생략했습니다. |
changed는 position.coords.latitude와 longitude를 읽어 메시지를 만들고 지도 iframe의 src를 갱신합니다. count가 5가 되면 clearWatch로 반복 서비스를 종료합니다.
- count가 5인지 확인합니다.
- 5라면 clearWatch(watchID)를 호출하고 종료 메시지를 출력합니다.
- 아니라면 lat, lon을 읽습니다.
- msg에 현재 좌표를 출력합니다.
- OpenStreetMap embed 주소를 만들어 map.src에 넣습니다.
- count를 1 증가시킵니다.
OpenStreetMap embed URL의 bbox는 지도의 표시 범위를 나타냅니다. 현재 경도와 위도에서 0.01씩 빼고 더해서 중심 주변 영역을 만듭니다.
| 값 | 의미 |
|---|---|
| lon - 0.01 | 왼쪽 경계 |
| lat - 0.01 | 아래쪽 경계 |
| lon + 0.01 | 오른쪽 경계 |
| lat + 0.01 | 위쪽 경계 |
HTTPS가 아닌 환경에서는 위치 정보가 막힐 수 있어서 원문은 sample 객체를 만들고 setInterval로 1초마다 좌표를 조금씩 줄입니다. 실제 위치 변화가 없어도 watchPosition 예제의 화면 변화를 확인할 수 있습니다.
- sample.coords.latitude는 37.5882에서 시작합니다.
- sample.coords.longitude는 127.009에서 시작합니다.
- changeLocation이 changed(sample)을 호출합니다.
- 호출 후 위도와 경도를 0.001씩 줄입니다.
- 5번 실행하면 clearInterval로 샘플 이동을 멈춥니다.
| 개선 | 이유 |
|---|---|
| error 콜백 추가 | 위치 권한 거부와 timeout을 처리합니다. |
| setInterval 문자열 제거 | 함수 참조 방식이 더 안전합니다. |
| id 이름 정리 | mute on/off 같은 공백 id를 피합니다. |
| 볼륨 슬라이더 추가 | 버튼보다 세밀하게 조절할 수 있습니다. |
| watch 중지 버튼 | 사용자가 위치 감시를 직접 멈출 수 있습니다. |
- video와 source 경로가 실제 파일 위치와 맞습니다.
- 버튼 id와 control 함수의 문자열 비교가 일치합니다.
- volume은 0과 1 사이로 제한됩니다.
- getSource가 SOURCE 태그를 찾을 수 있습니다.
- navigator.geolocation 지원 여부를 먼저 확인합니다.
- watchID를 저장해 clearWatch에 전달합니다.
- 지도 bbox 계산에 parseFloat를 사용합니다.
| 실수 | 문제 | 해결 |
|---|---|---|
| video.src만 읽음 | source 태그 구조에서는 빈 값처럼 보일 수 있습니다. | 자식 SOURCE 태그의 src를 찾습니다. |
| volume 범위 보정 생략 | 0 미만 또는 1 초과가 될 수 있습니다. | 증감 후 최소/최대 값을 제한합니다. |
| watchID를 저장하지 않음 | clearWatch로 반복 감시를 멈출 수 없습니다. | watchPosition 반환값을 변수에 저장합니다. |
| HTTPS 조건을 무시 | 실제 위치 요청이 실패할 수 있습니다. | HTTPS, localhost, 샘플 좌표를 고려합니다. |
| setInterval 문자열 실행 | 디버깅과 유지보수가 어렵습니다. | 함수 참조나 화살표 함수를 사용합니다. |
핵심 한 줄 요약
Tags
'php' 카테고리의 다른 글
| 오디오 플레이리스트 완전 정리 (0) | 2026.07.17 |
|---|---|
| Canvas 그림판 완전 정리 (0) | 2026.07.16 |
| JS Geolocation 완전 정리 (0) | 2026.07.16 |
| JS 오디오·비디오 제어 완전 정리 (0) | 2026.07.16 |
| 웹 스토리지 · 오디오/비디오 완전 정리 (0) | 2026.07.16 |
왕진 블로그

댓글