diff --git a/dashcam.html b/dashcam.html
index 4d8f2ab..bf6d0b1 100644
--- a/dashcam.html
+++ b/dashcam.html
@@ -14,35 +14,19 @@
#rec-dot { width: 7px; height: 7px; border-radius: 50%; background: #fff; animation: blink 1s infinite; }
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:0.2} }
-/* SMALL speedo — top right */
-#speed-display {
- position: absolute; top: 12px; right: 12px;
- text-align: center; background: rgba(0,0,0,0.45);
- border-radius: 12px; padding: 6px 14px;
- pointer-events: all; cursor: pointer;
- transition: opacity 0.2s;
-}
+#speed-display { position: absolute; top: 12px; right: 12px; text-align: center; background: rgba(0,0,0,0.45); border-radius: 12px; padding: 6px 14px; pointer-events: all; cursor: pointer; }
#speed-display:hover { background: rgba(255,255,255,0.12); }
#speed-val { font-size: 44px; font-weight: 700; color: #fff; line-height: 1; }
#speed-unit { font-size: 10px; color: #aaa; letter-spacing: 1.5px; margin-top: 1px; }
-/* BIG speedo overlay */
-#speedo-overlay {
- position: absolute; inset: 0;
- background: rgba(0,0,0,0.92);
- display: none; flex-direction: column;
- align-items: center; justify-content: center;
- pointer-events: all; cursor: pointer;
- z-index: 10;
-}
+/* flash effect on snapshot */
+#flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; z-index: 30; transition: opacity 0.05s; }
+#flash.on { opacity: 0.85; }
+
+/* big speedo */
+#speedo-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.92); display: none; flex-direction: column; align-items: center; justify-content: center; pointer-events: all; cursor: pointer; z-index: 10; }
#speedo-overlay.visible { display: flex; }
-#speedo-close {
- position: absolute; top: 12px; right: 14px;
- color: rgba(255,255,255,0.5); font-size: 22px;
- cursor: pointer; font-family: var(--font-sans);
- pointer-events: all; line-height: 1;
- background: none; border: none;
-}
+#speedo-close { position: absolute; top: 12px; right: 14px; color: rgba(255,255,255,0.5); font-size: 22px; cursor: pointer; font-family: var(--font-sans); pointer-events: all; line-height: 1; background: none; border: none; }
#speedo-close:hover { color: #fff; }
#big-speed-val { font-size: clamp(80px, 22vw, 160px); font-weight: 700; color: #fff; line-height: 1; text-align: center; }
#big-speed-unit { font-size: clamp(14px, 3vw, 22px); color: #aaa; letter-spacing: 3px; margin-top: 8px; text-align: center; }
@@ -52,7 +36,8 @@
.bdl { color: #555; font-size: clamp(9px, 1.5vw, 12px); letter-spacing: 0.5px; }
.bdv { color: #fff; font-weight: 500; }
-#gps-bar { position: absolute; bottom: 48px; left: 0; right: 0; background: rgba(0,0,0,0.5); padding: 5px 12px; display: none; }
+/* info bar */
+#gps-bar { position: absolute; bottom: 48px; left: 0; right: 0; background: rgba(0,0,0,0.55); padding: 5px 12px; display: none; }
.data-row { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
.di { font-size: 10px; color: #ccc; display: flex; gap: 4px; align-items: center; }
.dl { color: #666; font-size: 9px; letter-spacing: 0.4px; }
@@ -64,18 +49,23 @@
#status-bar { position: absolute; bottom: 90px; left: 12px; font-size: 10px; color: rgba(255,255,255,0.4); font-family: var(--font-sans); pointer-events: none; }
#placeholder { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; color: #888; gap: 10px; font-family: var(--font-sans); background: #000; }
-#btn-bar { position: absolute; bottom: 0; left: 0; right: 0; display: flex; justify-content: center; align-items: center; gap: 10px; padding: 7px 12px; background: rgba(0,0,0,0.5); pointer-events: all; flex-wrap: wrap; z-index: 20; }
-.hud-btn { background: rgba(255,255,255,0.1); border: 0.5px solid rgba(255,255,255,0.2); color: #fff; border-radius: 20px; padding: 5px 13px; font-size: 11px; font-family: var(--font-sans); cursor: pointer; letter-spacing: 0.4px; white-space: nowrap; }
+/* button bar */
+#btn-bar { position: absolute; bottom: 0; left: 0; right: 0; display: flex; justify-content: center; align-items: center; gap: 8px; padding: 7px 10px; background: rgba(0,0,0,0.5); pointer-events: all; flex-wrap: wrap; z-index: 20; }
+.hud-btn { background: rgba(255,255,255,0.1); border: 0.5px solid rgba(255,255,255,0.2); color: #fff; border-radius: 20px; padding: 5px 12px; font-size: 11px; font-family: var(--font-sans); cursor: pointer; letter-spacing: 0.4px; white-space: nowrap; }
.hud-btn:hover { background: rgba(255,255,255,0.2); }
.hud-btn:disabled { opacity: 0.3; cursor: default; }
.hud-btn.primary { background: rgba(29,158,117,0.7); border-color: #1D9E75; }
.hud-btn.primary:hover { background: rgba(29,158,117,0.9); }
.hud-btn.danger { background: rgba(180,0,0,0.7); border-color: rgba(220,0,0,0.9); }
.hud-btn.danger:hover { background: rgba(220,0,0,0.85); }
+.hud-btn.active { background: rgba(186,117,23,0.7); border-color: rgba(186,117,23,0.9); }
+canvas { display: none; }
+
+
🎥
@@ -95,13 +85,11 @@
00:00
-
-
--
@@ -137,9 +125,11 @@
-
+
+
+
-
+
@@ -151,7 +141,7 @@ let useMph = true, maxSpeed = 0;
let lastPos = null, totalDist = 0;
let mediaRecorder = null, recordedChunks = [];
let recInterval = null, recSeconds = 0, isRecording = false;
-let speedoOpen = false;
+let speedoOpen = false, infoVisible = false;
let srtEntries = [], recStartTime = null;
let currentGPS = { lat: null, lng: null, alt: null, acc: null, hdg: null, speed: 0 };
@@ -160,14 +150,14 @@ function cvtLabel() { return useMph ? 'mph' : 'kph'; }
function haversine(a, b) {
const R = 6371000, r = Math.PI / 180;
- const dLat = (b.lat - a.lat) * r, dLng = (b.lng - a.lng) * r;
+ const dLat = (b.lat-a.lat)*r, dLng = (b.lng-a.lng)*r;
const x = Math.sin(dLat/2)**2 + Math.cos(a.lat*r)*Math.cos(b.lat*r)*Math.sin(dLng/2)**2;
return R * 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1-x));
}
function bearingLabel(deg) {
if (deg === null || isNaN(deg)) return '--';
- return ['N','NE','E','SE','S','SW','W','NW'][Math.round(deg/45)%8] + ' ' + Math.round(deg) + '\xb0';
+ return ['N','NE','E','SE','S','SW','W','NW'][Math.round(deg/45)%8]+' '+Math.round(deg)+'\xb0';
}
function pad(v) { return String(Math.floor(v)).padStart(2,'0'); }
@@ -176,13 +166,67 @@ function pad3(v) { return String(Math.floor(v)).padStart(3,'0'); }
function updateClock() {
const n = new Date();
document.getElementById('clock').textContent = pad(n.getHours())+':'+pad(n.getMinutes())+':'+pad(n.getSeconds());
- const days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
- const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
+ const days=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
+ const months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
document.getElementById('dateline').textContent = days[n.getDay()]+' '+pad(n.getDate())+' '+months[n.getMonth()]+' '+n.getFullYear();
}
function setStatus(msg) { document.getElementById('status-bar').textContent = msg; }
+function toggleInfo() {
+ infoVisible = !infoVisible;
+ const bar = document.getElementById('gps-bar');
+ const btn = document.getElementById('info-btn');
+ bar.style.display = infoVisible ? 'block' : 'none';
+ btn.classList.toggle('active', infoVisible);
+ btn.textContent = infoVisible ? 'INFO ✓' : 'INFO';
+}
+
+function takeSnapshot() {
+ if (!stream) return;
+ const video = document.getElementById('video');
+ const canvas = document.getElementById('snap-canvas');
+ canvas.width = video.videoWidth || 1280;
+ canvas.height = video.videoHeight || 720;
+ const ctx = canvas.getContext('2d');
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+
+ // stamp telemetry onto image
+ const n = new Date();
+ const dateStr = n.getFullYear()+'-'+pad(n.getMonth()+1)+'-'+pad(n.getDate())+' '+pad(n.getHours())+':'+pad(n.getMinutes())+':'+pad(n.getSeconds());
+ const spd = currentGPS.speed !== null ? Math.round(cvt(currentGPS.speed))+' '+cvtLabel().toUpperCase() : '--';
+ const lat = currentGPS.lat !== null ? currentGPS.lat.toFixed(6) : '--';
+ const lng = currentGPS.lng !== null ? currentGPS.lng.toFixed(6) : '--';
+ const alt = currentGPS.alt !== null ? Math.round(currentGPS.alt)+'m' : '--';
+ const lines = [dateStr, spd+' '+bearingLabel(currentGPS.hdg), 'LAT '+lat+' LNG '+lng, 'ALT '+alt];
+
+ ctx.font = 'bold 20px monospace';
+ ctx.textBaseline = 'bottom';
+ const lineH = 26, pad8 = 10;
+ const boxH = lines.length * lineH + pad8 * 2;
+ ctx.fillStyle = 'rgba(0,0,0,0.55)';
+ ctx.fillRect(0, canvas.height - boxH, canvas.width, boxH);
+ ctx.fillStyle = '#ffffff';
+ lines.forEach((l, i) => {
+ ctx.fillText(l, pad8, canvas.height - boxH + pad8 + (i+1)*lineH);
+ });
+
+ // flash
+ const flash = document.getElementById('flash');
+ flash.classList.add('on');
+ setTimeout(() => flash.classList.remove('on'), 120);
+
+ // download
+ canvas.toBlob(blob => {
+ const fname = 'dashcam_snap_'+n.getFullYear()+pad(n.getMonth()+1)+pad(n.getDate())+'_'+pad(n.getHours())+pad(n.getMinutes())+pad(n.getSeconds())+'.jpg';
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url; a.download = fname; a.click();
+ setTimeout(() => URL.revokeObjectURL(url), 5000);
+ setStatus('Snapshot saved');
+ }, 'image/jpeg', 0.92);
+}
+
function openSpeedo() {
if (isRecording) return;
speedoOpen = true;
@@ -209,8 +253,7 @@ function syncBigSpeedo() {
}
function toSRTTime(ms) {
- const h = Math.floor(ms/3600000), m = Math.floor((ms%3600000)/60000);
- const s = Math.floor((ms%60000)/1000), mil = ms%1000;
+ const h=Math.floor(ms/3600000), m=Math.floor((ms%3600000)/60000), s=Math.floor((ms%60000)/1000), mil=ms%1000;
return pad(h)+':'+pad(m)+':'+pad(s)+','+pad3(mil);
}
@@ -221,36 +264,35 @@ function captureSRTFrame() {
const timeStr = pad(now.getHours())+':'+pad(now.getMinutes())+':'+pad(now.getSeconds());
const spd = currentGPS.speed !== null ? Math.round(cvt(currentGPS.speed)) : '--';
srtEntries.push({
- startMs: elapsed, endMs: elapsed + 1000,
+ startMs: elapsed, endMs: elapsed+1000,
lines: [
- dateStr + ' ' + timeStr,
- 'Speed: ' + spd + ' ' + cvtLabel() + ' Hdg: ' + bearingLabel(currentGPS.hdg),
- 'Lat: ' + (currentGPS.lat !== null ? currentGPS.lat.toFixed(6) : '--') + ' Lng: ' + (currentGPS.lng !== null ? currentGPS.lng.toFixed(6) : '--'),
- 'Alt: ' + (currentGPS.alt !== null ? Math.round(currentGPS.alt)+'m' : '--') + ' Acc: ' + (currentGPS.acc !== null ? Math.round(currentGPS.acc)+'m' : '--')
+ dateStr+' '+timeStr,
+ 'Speed: '+spd+' '+cvtLabel()+' Hdg: '+bearingLabel(currentGPS.hdg),
+ 'Lat: '+(currentGPS.lat!==null?currentGPS.lat.toFixed(6):'--')+' Lng: '+(currentGPS.lng!==null?currentGPS.lng.toFixed(6):'--'),
+ 'Alt: '+(currentGPS.alt!==null?Math.round(currentGPS.alt)+'m':'--')+' Acc: '+(currentGPS.acc!==null?Math.round(currentGPS.acc)+'m':'--')
]
});
}
function buildSRT() {
- return srtEntries.map((e,i) => (i+1)+'\n'+toSRTTime(e.startMs)+' --> '+toSRTTime(e.endMs)+'\n'+e.lines.join('\n')).join('\n\n')+'\n';
+ return srtEntries.map((e,i)=>(i+1)+'\n'+toSRTTime(e.startMs)+' --> '+toSRTTime(e.endMs)+'\n'+e.lines.join('\n')).join('\n\n')+'\n';
}
function getFilename() {
- const n = new Date();
+ const n=new Date();
return 'dashcam_'+n.getFullYear()+pad(n.getMonth()+1)+pad(n.getDate())+'_'+pad(n.getHours())+pad(n.getMinutes())+pad(n.getSeconds());
}
function getBestMimeType() {
- const types = ['video/webm;codecs=vp9','video/webm;codecs=vp8','video/webm','video/mp4'];
- for (const t of types) { if (MediaRecorder.isTypeSupported(t)) return t; }
+ const types=['video/webm;codecs=vp9','video/webm;codecs=vp8','video/webm','video/mp4'];
+ for(const t of types){if(MediaRecorder.isTypeSupported(t))return t;}
return '';
}
function dl(filename, blob) {
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url; a.download = filename; a.click();
- setTimeout(() => URL.revokeObjectURL(url), 5000);
+ const url=URL.createObjectURL(blob), a=document.createElement('a');
+ a.href=url; a.download=filename; a.click();
+ setTimeout(()=>URL.revokeObjectURL(url),5000);
}
function toggleRecord() {
@@ -258,38 +300,35 @@ function toggleRecord() {
const btn = document.getElementById('rec-btn');
const ind = document.getElementById('rec-indicator');
if (!isRecording) {
- recordedChunks = []; srtEntries = []; recStartTime = Date.now();
- const mime = getBestMimeType();
- try { mediaRecorder = new MediaRecorder(stream, mime ? { mimeType: mime } : {}); }
- catch(e) { mediaRecorder = new MediaRecorder(stream); }
- mediaRecorder.ondataavailable = e => { if (e.data && e.data.size > 0) recordedChunks.push(e.data); };
- mediaRecorder.onstop = () => {
- const name = getFilename();
- const mime2 = getBestMimeType();
- const ext = mime2.includes('mp4') ? 'mp4' : 'webm';
- dl(name+'.'+ext, new Blob(recordedChunks, { type: mime2 }));
- setTimeout(() => dl(name+'.srt', new Blob([buildSRT()], { type: 'text/plain' })), 800);
- recordedChunks = [];
+ recordedChunks=[]; srtEntries=[]; recStartTime=Date.now();
+ const mime=getBestMimeType();
+ try { mediaRecorder=new MediaRecorder(stream,mime?{mimeType:mime}:{}); }
+ catch(e) { mediaRecorder=new MediaRecorder(stream); }
+ mediaRecorder.ondataavailable=e=>{if(e.data&&e.data.size>0)recordedChunks.push(e.data);};
+ mediaRecorder.onstop=()=>{
+ const name=getFilename(), mime2=getBestMimeType(), ext=mime2.includes('mp4')?'mp4':'webm';
+ dl(name+'.'+ext, new Blob(recordedChunks,{type:mime2}));
+ setTimeout(()=>dl(name+'.srt',new Blob([buildSRT()],{type:'text/plain'})),800);
+ recordedChunks=[];
setStatus('Saved video + SRT');
};
mediaRecorder.start(1000);
- isRecording = true; recSeconds = 0;
- ind.style.display = 'flex';
- btn.innerHTML = '▮▮ SAVE';
+ isRecording=true; recSeconds=0;
+ ind.style.display='flex';
+ btn.innerHTML='▮▮ SAVE';
btn.classList.add('danger');
captureSRTFrame();
- recInterval = setInterval(() => {
+ recInterval=setInterval(()=>{
recSeconds++;
- document.getElementById('rec-timer').textContent = pad(Math.floor(recSeconds/60))+':'+pad(recSeconds%60);
+ document.getElementById('rec-timer').textContent=pad(Math.floor(recSeconds/60))+':'+pad(recSeconds%60);
captureSRTFrame();
- }, 1000);
+ },1000);
setStatus('Recording...');
} else {
- mediaRecorder.stop();
- isRecording = false;
+ mediaRecorder.stop(); isRecording=false;
clearInterval(recInterval);
- ind.style.display = 'none';
- btn.innerHTML = '● RECORD';
+ ind.style.display='none';
+ btn.innerHTML='● REC';
btn.classList.remove('danger');
setStatus('Saving...');
}
@@ -297,85 +336,81 @@ function toggleRecord() {
function startGPS() {
if (!navigator.geolocation) { setStatus('GPS unavailable'); return; }
- document.getElementById('gps-bar').style.display = 'block';
- watchId = navigator.geolocation.watchPosition(pos => {
- const c = pos.coords;
- currentGPS = { lat: c.latitude, lng: c.longitude, alt: c.altitude, acc: c.accuracy, hdg: c.heading, speed: c.speed !== null ? c.speed : 0 };
- const conv = cvt(currentGPS.speed);
- if (conv > maxSpeed) maxSpeed = conv;
- const cur = { lat: c.latitude, lng: c.longitude };
- if (lastPos) { const d = haversine(lastPos, cur); if (d < 200) totalDist += d; }
- lastPos = cur;
- document.getElementById('speed-val').textContent = Math.round(conv);
- document.getElementById('lat-val').textContent = c.latitude.toFixed(5);
- document.getElementById('lng-val').textContent = c.longitude.toFixed(5);
- document.getElementById('alt-val').textContent = c.altitude !== null ? Math.round(c.altitude)+'m' : '--';
- document.getElementById('acc-val').textContent = Math.round(c.accuracy)+'m';
- document.getElementById('hdg-val').textContent = bearingLabel(c.heading);
- document.getElementById('dist-val').textContent = (totalDist/1000).toFixed(2)+'km';
- document.getElementById('gps-dot').className = 'active';
+ watchId=navigator.geolocation.watchPosition(pos=>{
+ const c=pos.coords;
+ currentGPS={lat:c.latitude,lng:c.longitude,alt:c.altitude,acc:c.accuracy,hdg:c.heading,speed:c.speed!==null?c.speed:0};
+ const conv=cvt(currentGPS.speed);
+ if(conv>maxSpeed) maxSpeed=conv;
+ const cur={lat:c.latitude,lng:c.longitude};
+ if(lastPos){const d=haversine(lastPos,cur);if(d<200)totalDist+=d;}
+ lastPos=cur;
+ document.getElementById('speed-val').textContent=Math.round(conv);
+ document.getElementById('lat-val').textContent=c.latitude.toFixed(5);
+ document.getElementById('lng-val').textContent=c.longitude.toFixed(5);
+ document.getElementById('alt-val').textContent=c.altitude!==null?Math.round(c.altitude)+'m':'--';
+ document.getElementById('acc-val').textContent=Math.round(c.accuracy)+'m';
+ document.getElementById('hdg-val').textContent=bearingLabel(c.heading);
+ document.getElementById('dist-val').textContent=(totalDist/1000).toFixed(2)+'km';
+ document.getElementById('gps-dot').className='active';
syncBigSpeedo();
setStatus('');
- }, err => {
- setStatus('GPS: ' + err.message);
- document.getElementById('gps-dot').className = '';
- }, { enableHighAccuracy: true, maximumAge: 1000, timeout: 15000 });
+ }, err=>{
+ setStatus('GPS: '+err.message);
+ document.getElementById('gps-dot').className='';
+ },{enableHighAccuracy:true,maximumAge:1000,timeout:15000});
}
async function startDashcam() {
- const btn = document.getElementById('start-btn');
- btn.disabled = true; btn.textContent = '...';
- if (isRecording) toggleRecord();
+ const btn=document.getElementById('start-btn');
+ btn.disabled=true; btn.textContent='...';
+ if(isRecording) toggleRecord();
closeSpeedo();
try {
- if (stream) stream.getTracks().forEach(t => t.stop());
- stream = await navigator.mediaDevices.getUserMedia({
- video: { facingMode, width: { ideal: 1920 }, height: { ideal: 1080 } }, audio: false
- });
- document.getElementById('video').srcObject = stream;
- document.getElementById('placeholder').style.display = 'none';
- document.getElementById('top-left').style.display = 'flex';
- document.getElementById('flip-btn').disabled = false;
- document.getElementById('rec-btn').disabled = false;
- btn.textContent = 'RESTART'; btn.disabled = false;
- if (watchId !== null) { navigator.geolocation.clearWatch(watchId); watchId = null; }
- maxSpeed = 0; totalDist = 0; lastPos = null;
- currentGPS = { lat: null, lng: null, alt: null, acc: null, hdg: null, speed: 0 };
+ if(stream) stream.getTracks().forEach(t=>t.stop());
+ stream=await navigator.mediaDevices.getUserMedia({video:{facingMode,width:{ideal:1920},height:{ideal:1080}},audio:false});
+ document.getElementById('video').srcObject=stream;
+ document.getElementById('placeholder').style.display='none';
+ document.getElementById('top-left').style.display='flex';
+ document.getElementById('flip-btn').disabled=false;
+ document.getElementById('rec-btn').disabled=false;
+ document.getElementById('snap-btn').disabled=false;
+ document.getElementById('info-btn').disabled=false;
+ btn.textContent='RESTART'; btn.disabled=false;
+ if(watchId!==null){navigator.geolocation.clearWatch(watchId);watchId=null;}
+ maxSpeed=0; totalDist=0; lastPos=null;
+ currentGPS={lat:null,lng:null,alt:null,acc:null,hdg:null,speed:0};
startGPS();
- if (clockInterval) clearInterval(clockInterval);
- clockInterval = setInterval(updateClock, 1000);
+ if(clockInterval) clearInterval(clockInterval);
+ clockInterval=setInterval(updateClock,1000);
updateClock();
setStatus('Acquiring GPS...');
} catch(e) {
- setStatus('Camera: ' + e.message);
- btn.textContent = 'START'; btn.disabled = false;
+ setStatus('Camera: '+e.message);
+ btn.textContent='START'; btn.disabled=false;
}
}
-function switchCamera() { facingMode = facingMode === 'environment' ? 'user' : 'environment'; startDashcam(); }
+function switchCamera() { facingMode=facingMode==='environment'?'user':'environment'; startDashcam(); }
function toggleUnit() {
- useMph = !useMph;
- maxSpeed = useMph ? maxSpeed / 3.6 * 2.23694 : maxSpeed / 2.23694 * 3.6;
- const unit = useMph ? 'MPH' : 'KPH';
- document.getElementById('speed-unit').textContent = unit;
- document.getElementById('big-speed-unit').textContent = unit;
+ useMph=!useMph;
+ maxSpeed=useMph?maxSpeed/3.6*2.23694:maxSpeed/2.23694*3.6;
+ const unit=useMph?'MPH':'KPH';
+ document.getElementById('speed-unit').textContent=unit;
+ document.getElementById('big-speed-unit').textContent=unit;
}
function toggleFullscreen() {
- const app = document.getElementById('app');
- const btn = document.getElementById('fs-btn');
- if (!app.classList.contains('fullscreen')) {
- if (app.requestFullscreen) app.requestFullscreen().catch(()=>{});
- app.classList.add('fullscreen');
- btn.textContent = '\u2715 EXIT';
+ const app=document.getElementById('app'), btn=document.getElementById('fs-btn');
+ if(!app.classList.contains('fullscreen')){
+ if(app.requestFullscreen) app.requestFullscreen().catch(()=>{});
+ app.classList.add('fullscreen'); btn.textContent='\u2715';
} else {
- if (document.exitFullscreen && document.fullscreenElement) document.exitFullscreen().catch(()=>{});
- app.classList.remove('fullscreen');
- btn.textContent = '\u26f6 FULL';
+ if(document.exitFullscreen&&document.fullscreenElement) document.exitFullscreen().catch(()=>{});
+ app.classList.remove('fullscreen'); btn.textContent='\u26f6';
}
- document.addEventListener('fullscreenchange', () => {
- if (!document.fullscreenElement) { app.classList.remove('fullscreen'); btn.textContent = '\u26f6 FULL'; }
- }, { once: true });
+ document.addEventListener('fullscreenchange',()=>{
+ if(!document.fullscreenElement){app.classList.remove('fullscreen');btn.textContent='\u26f6';}
+ },{once:true});
}