店舗案内

■所在地
〒150-0001 東京都東京都渋谷区神宮前3-42-2

○○○線「○○○駅」より徒歩○○分
○○○線「○○○駅」より徒歩○○分

■電話番号
00-0000-0000

■営業時間・定休日
00:00~00:00(○曜日休業)

ご相談・お問合せ

お電話でのご相談・お問合せは、以下の電話番号までご連絡ください。

00-0000-0000
受付時間 00:00~00:00

ご質問などございましたら、以下のお問合せフォームよりお気軽にお問合せください。

お問合せ
ご相談・お問合せはこちら
カメラ撮影サイト(Android最終修正)

カメラで撮影しよう!(Android最終修正)

デバッグ情報: 読み込み中...

撮影した写真

📁 ギャラリー

const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); const photo = document.getElementById('photo'); const recordedVideo = document.getElementById('recordedVideo'); const modeSelect = document.getElementById('mode'); const cameraSelect = document.getElementById('cameraSelect'); const startBtn = document.getElementById('start'); const fullscreenBtn = document.getElementById('fullscreen'); const captureBtn = document.getElementById('capture'); const recordBtn = document.getElementById('record'); const stopRecordBtn = document.getElementById('stopRecord'); const downloadBtn = document.getElementById('download'); const photoControls = document.getElementById('photoControls'); const videoControls = document.getElementById('videoControls'); const output = document.getElementById('output'); const gallery = document.getElementById('gallery'); const clearGalleryBtn = document.getElementById('clearGallery'); const modal = document.getElementById('modal'); const modalContent = document.getElementById('modalContent'); const closeModal = document.querySelector('.close'); const debugInfo = document.getElementById('debugInfo'); const ctx = canvas.getContext('2d'); let stream = null; let mediaRecorder = null; let recordedChunks = []; let currentFacingMode = 'user'; let galleryItems = JSON.parse(localStorage.getItem('cameraGallery') || '[]'); // セキュアコンテキストチェック function checkSecureContext() { const isSecure = window.isSecureContext; debugInfo.textContent = isSecure ? '✅ セキュア' : '❌ 非セキュア!'; return isSecure; } // Permissions APIで権限チェック(Android Chrome向け) async function checkCameraPermission() { if ('permissions' in navigator) { try { const result = await navigator.permissions.query({ name: 'camera' }); debugInfo.textContent += ` | 権限: ${result.state}`; if (result.state === 'denied') { alert('カメラ権限が拒否されています。ブラウザ設定で許可を!'); return false; } return result.state === 'granted'; } catch (err) { console.error('権限チェックエラー:', err); } } return true; } // APIサポートチェック if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { alert('ブラウザ非対応。Chrome最新版を!'); debugInfo.textContent = '❌ 非対応'; throw new Error('Unsupported browser'); } // ギャラリー機能(以前と同じ、略) function renderGallery() { gallery.innerHTML = ''; galleryItems.forEach((item, index) => { const div = document.createElement('div'); div.className = 'gallery-item'; if (item.type === 'photo') { const img = document.createElement('img'); img.src = item.url; img.alt = `写真 ${index + 1}`; img. = () => openModal(img.src, 'photo'); div.appendChild(img); } else { const vid = document.createElement('video'); vid.src = item.url; vid.controls = false; vid.muted = true; vid. = () => openModal(vid.src, 'video'); div.appendChild(vid); } const delBtn = document.createElement('button'); delBtn.textContent = '削除'; delBtn.style.fontSize = '12px'; delBtn.style.marginTop = '5px'; delBtn. = (e) => { e.stopPropagation(); deleteItem(index); }; div.appendChild(delBtn); gallery.appendChild(div); }); } function saveGallery() { localStorage.setItem('cameraGallery', JSON.stringify(galleryItems)); } function addToGallery(url, type) { galleryItems.unshift({ url, type, timestamp: Date.now() }); if (galleryItems.length > 50) galleryItems = galleryItems.slice(0, 50); saveGallery(); renderGallery(); } function deleteItem(index) { galleryItems.splice(index, 1); saveGallery(); renderGallery(); } function openModal(src, type) { modalContent.innerHTML = ''; if (type === 'photo') { const img = document.createElement('img'); img.src = src; modalContent.appendChild(img); } else { const vid = document.createElement('video'); vid.src = src; vid.controls = true; vid.playsinline = true; modalContent.appendChild(vid); } modal.style.display = 'block'; } closeModal. = () => { modal.style.display = 'none'; }; window. = (e) => { if (e.target === modal) modal.style.display = 'none'; }; clearGalleryBtn. = () => { if (confirm('クリアしますか?')) { galleryItems = []; saveGallery(); renderGallery(); } }; // モード切り替え modeSelect.addEventListener('change', (e) => { const mode = e.target.value; if (stream) stopStream(); updateUIForMode(mode); }); function updateUIForMode(mode) { if (mode === 'photo') { photoControls.style.display = 'block'; videoControls.style.display = 'none'; photo.style.display = 'block'; recordedVideo.style.display = 'none'; captureBtn.disabled = !stream; } else { photoControls.style.display = 'none'; videoControls.style.display = 'block'; photo.style.display = 'none'; recordedVideo.style.display = 'block'; recordBtn.disabled = !stream; } output.style.display = 'block'; downloadBtn.style.display = 'none'; } // カメラ選択 cameraSelect.addEventListener('change', (e) => { currentFacingMode = e.target.value; if (stream) { stopStream(); startCamera(); } }); // ストリーム停止 function stopStream() { if (stream) { stream.getTracks().forEach(track => track.stop()); stream = null; video.srcObject = null; // 黒い画面クリア } startBtn.disabled = false; fullscreenBtn.disabled = true; recordBtn.disabled = true; captureBtn.disabled = true; stopRecordBtn.disabled = true; } // デバイス変更イベント(自動再取得) navigator.mediaDevices.ondevicechange = () => { console.log('デバイス変更検知。再取得中...'); if (stream) stopStream(); startCamera(); }; // カメラ開始(シンプルconstraints + 権限チェック) async function startCamera() { try { if (!checkSecureContext()) throw new Error('非セキュア'); const hasPermission = await checkCameraPermission(); if (!hasPermission) throw new Error('権限なし'); // 超シンプルconstraints(Android黒い画面回避) const constraints = { video: { facingMode: currentFacingMode === 'default' ? 'user' : currentFacingMode } // 解像度指定なしで安定 }; debugInfo.textContent = '🔄 許可求め中...'; stream = await navigator.mediaDevices.getUserMedia(constraints); video.srcObject = stream; await video.play(); startBtn.disabled = true; fullscreenBtn.disabled = false; debugInfo.textContent = '✅ 成功!映ってるはず'; const mode = modeSelect.value; if (mode === 'photo') captureBtn.disabled = false; else recordBtn.disabled = false; } catch (err) { console.error('エラー:', err); let msg = `エラー: ${err.name} - ${err.message}`; if (err.name === 'NotAllowedError') msg += '\n権限拒否。設定確認を!'; else if (err.name === 'NotReadableError') msg += '\nカメラ使用中。アプリ閉じて。'; alert(msg); debugInfo.textContent = `❌ ${err.name}`; } } startBtn.addEventListener('click', startCamera); // フルスクリーン fullscreenBtn.addEventListener('click', () => { if (video.requestFullscreen) video.requestFullscreen(); else if (video.webkitRequestFullscreen) video.webkitRequestFullscreen(); }); // 写真撮影 captureBtn.addEventListener('click', () => { canvas.width = video.videoWidth || 640; canvas.height = video.videoHeight || 480; ctx.drawImage(video, 0, 0); const dataUrl = canvas.toDataURL('image/png'); photo.src = dataUrl; photo.style.display = 'block'; addToGallery(dataUrl, 'photo'); downloadBtn.href = dataUrl; downloadBtn.download = 'photo.png'; downloadBtn.textContent = '💾 写真ダウンロード'; downloadBtn.style.display = 'inline-block'; downloadBtn.style.fontSize = '18px'; downloadBtn.style.padding = '15px 25px'; downloadBtn.style.textDecoration = 'none'; downloadBtn.style.background = '#28a745'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '8px'; }); // 動画録画開始 recordBtn.addEventListener('click', () => { recordedChunks = []; mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' }); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) recordedChunks.push(e.data); }; mediaRecorder.onstop = () => { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); recordedVideo.src = url; recordedVideo.style.display = 'block'; addToGallery(url, 'video'); downloadBtn.href = url; downloadBtn.download = 'video.webm'; downloadBtn.textContent = '💾 動画ダウンロード'; downloadBtn.style.display = 'inline-block'; downloadBtn.style.fontSize = '18px'; downloadBtn.style.padding = '15px 25px'; downloadBtn.style.textDecoration = 'none'; downloadBtn.style.background = '#28a745'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '8px'; }; mediaRecorder.start(1000); recordBtn.disabled = true; stopRecordBtn.disabled = false; recordBtn.textContent = '⏸ 録画中...'; }); // 動画録画停止 stopRecordBtn.addEventListener('click', () => { if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); } recordBtn.disabled = false; stopRecordBtn.disabled = true; recordBtn.textContent = '▶ 録画開始'; }); // 初期化 updateUIForMode(modeSelect.value); renderGallery(); checkSecureContext(); // ページ終了時クリーンアップ window.addEventListener('beforeunload', stopStream);
カメラ撮影サイト(Android修正版)

カメラで撮影しよう!(Android修正版)

デバッグ情報: 読み込み中...

撮影した写真

📁 ギャラリー

const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); const photo = document.getElementById('photo'); const recordedVideo = document.getElementById('recordedVideo'); const modeSelect = document.getElementById('mode'); const cameraSelect = document.getElementById('cameraSelect'); const startBtn = document.getElementById('start'); const fullscreenBtn = document.getElementById('fullscreen'); const captureBtn = document.getElementById('capture'); const recordBtn = document.getElementById('record'); const stopRecordBtn = document.getElementById('stopRecord'); const downloadBtn = document.getElementById('download'); const photoControls = document.getElementById('photoControls'); const videoControls = document.getElementById('videoControls'); const output = document.getElementById('output'); const gallery = document.getElementById('gallery'); const clearGalleryBtn = document.getElementById('clearGallery'); const modal = document.getElementById('modal'); const modalContent = document.getElementById('modalContent'); const closeModal = document.querySelector('.close'); const debugInfo = document.getElementById('debugInfo'); const ctx = canvas.getContext('2d'); let stream = null; let mediaRecorder = null; let recordedChunks = []; let currentFacingMode = 'user'; let galleryItems = JSON.parse(localStorage.getItem('cameraGallery') || '[]'); // セキュアコンテキストチェック function checkSecureContext() { const isSecure = window.isSecureContext; const protocol = location.protocol; debugInfo.textContent = isSecure ? '✅ セキュア(許可画面が出るはず)' : '❌ 非セキュア! HTTPS/localhostに変更を'; if (!isSecure) { alert('非セキュア環境です! localhostサーバーでテストしてください。許可画面が出ません。'); } return isSecure; } // APIサポートチェック if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { alert('このブラウザはカメラをサポートしていません。最新のChromeをおすすめします。'); debugInfo.textContent = '❌ ブラウザ非対応'; throw new Error('Unsupported browser'); } // ギャラリー機能(省略、以前と同じ) function renderGallery() { gallery.innerHTML = ''; galleryItems.forEach((item, index) => { const div = document.createElement('div'); div.className = 'gallery-item'; if (item.type === 'photo') { const img = document.createElement('img'); img.src = item.url; img.alt = `写真 ${index + 1}`; img. = () => openModal(img.src, 'photo'); div.appendChild(img); } else { const vid = document.createElement('video'); vid.src = item.url; vid.controls = false; vid.muted = true; vid. = () => openModal(vid.src, 'video'); div.appendChild(vid); } const delBtn = document.createElement('button'); delBtn.textContent = '削除'; delBtn.style.fontSize = '12px'; delBtn.style.marginTop = '5px'; delBtn. = (e) => { e.stopPropagation(); deleteItem(index); }; div.appendChild(delBtn); gallery.appendChild(div); }); } function saveGallery() { localStorage.setItem('cameraGallery', JSON.stringify(galleryItems)); } function addToGallery(url, type) { galleryItems.unshift({ url, type, timestamp: Date.now() }); if (galleryItems.length > 50) galleryItems = galleryItems.slice(0, 50); saveGallery(); renderGallery(); } function deleteItem(index) { galleryItems.splice(index, 1); saveGallery(); renderGallery(); } function openModal(src, type) { modalContent.innerHTML = ''; if (type === 'photo') { const img = document.createElement('img'); img.src = src; modalContent.appendChild(img); } else { const vid = document.createElement('video'); vid.src = src; vid.controls = true; vid.playsinline = true; modalContent.appendChild(vid); } modal.style.display = 'block'; } closeModal. = () => { modal.style.display = 'none'; }; window. = (e) => { if (e.target === modal) modal.style.display = 'none'; }; clearGalleryBtn. = () => { if (confirm('ギャラリーをクリアしますか?')) { galleryItems = []; saveGallery(); renderGallery(); } }; // モード切り替え modeSelect.addEventListener('change', (e) => { const mode = e.target.value; if (stream) stopStream(); updateUIForMode(mode); }); function updateUIForMode(mode) { if (mode === 'photo') { photoControls.style.display = 'block'; videoControls.style.display = 'none'; photo.style.display = 'block'; recordedVideo.style.display = 'none'; captureBtn.disabled = !stream; } else { photoControls.style.display = 'none'; videoControls.style.display = 'block'; photo.style.display = 'none'; recordedVideo.style.display = 'block'; recordBtn.disabled = !stream; } output.style.display = 'block'; downloadBtn.style.display = 'none'; } // カメラ選択 cameraSelect.addEventListener('change', (e) => { currentFacingMode = e.target.value; if (stream) { stopStream(); startCamera(); } }); // ストリーム停止(強化: 完全停止) function stopStream() { if (stream) { stream.getTracks().forEach(track => { track.stop(); }); stream = null; video.srcObject = null; // 重要: ソースをクリアして黒い画面回避 } startBtn.disabled = false; fullscreenBtn.disabled = true; recordBtn.disabled = true; captureBtn.disabled = true; stopRecordBtn.disabled = true; } // カメラ開始(Android向けconstraints簡略化) async function startCamera() { try { if (!checkSecureContext()) { throw new Error('非セキュアコンテキスト'); } // Android黒い画面回避: シンプルconstraints + デフォルトfacingMode const constraints = { video: { facingMode: currentFacingMode === 'default' ? 'user' : currentFacingMode, // デフォルトをuserに width: { ideal: 640 }, // 低解像度で安定 height: { ideal: 480 } }, audio: false }; debugInfo.textContent = '🔄 許可を求め中...'; stream = await navigator.mediaDevices.getUserMedia(constraints); video.srcObject = stream; await video.play(); // 明示的にplay startBtn.disabled = true; fullscreenBtn.disabled = false; debugInfo.textContent = '✅ カメラ接続成功!'; const mode = modeSelect.value; if (mode === 'photo') captureBtn.disabled = false; else recordBtn.disabled = false; } catch (err) { console.error('詳細エラー:', err); let errorMsg = `エラー: ${err.name} - ${err.message}`; if (err.name === 'NotAllowedError') errorMsg += '\n許可ブロック。Chrome設定 > カメラ > 許可を!'; else if (err.name === 'NotFoundError') errorMsg += '\nカメラなし。'; else if (err.name === 'OverconstrainedError') errorMsg += '\n設定ミス。デフォルトカメラで再試行。'; else if (err.name === 'NotReadableError') errorMsg += '\nカメラ使用中。アプリ閉じて。'; else errorMsg += '\nコンソール(F12)確認を!'; alert(errorMsg); debugInfo.textContent = `❌ ${err.name}: ${err.message}`; } } startBtn.addEventListener('click', startCamera); // フルスクリーン fullscreenBtn.addEventListener('click', () => { if (video.requestFullscreen) video.requestFullscreen(); else if (video.webkitRequestFullscreen) video.webkitRequestFullscreen(); }); // 写真撮影 captureBtn.addEventListener('click', () => { canvas.width = video.videoWidth || 640; canvas.height = video.videoHeight || 480; ctx.drawImage(video, 0, 0); const dataUrl = canvas.toDataURL('image/png'); photo.src = dataUrl; photo.style.display = 'block'; addToGallery(dataUrl, 'photo'); downloadBtn.href = dataUrl; downloadBtn.download = 'photo.png'; downloadBtn.textContent = '💾 写真をダウンロード'; downloadBtn.style.display = 'inline-block'; downloadBtn.style.fontSize = '18px'; downloadBtn.style.padding = '15px 25px'; downloadBtn.style.textDecoration = 'none'; downloadBtn.style.background = '#28a745'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '8px'; }); // 動画録画開始 recordBtn.addEventListener('click', () => { recordedChunks = []; mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' }); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) recordedChunks.push(e.data); }; mediaRecorder.onstop = () => { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); recordedVideo.src = url; recordedVideo.style.display = 'block'; addToGallery(url, 'video'); downloadBtn.href = url; downloadBtn.download = 'video.webm'; downloadBtn.textContent = '💾 動画をダウンロード'; downloadBtn.style.display = 'inline-block'; downloadBtn.style.fontSize = '18px'; downloadBtn.style.padding = '15px 25px'; downloadBtn.style.textDecoration = 'none'; downloadBtn.style.background = '#28a745'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '8px'; }; mediaRecorder.start(1000); recordBtn.disabled = true; stopRecordBtn.disabled = false; recordBtn.textContent = '⏸ 録画中...'; }); // 動画録画停止 stopRecordBtn.addEventListener('click', () => { if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); } recordBtn.disabled = false; stopRecordBtn.disabled = true; recordBtn.textContent = '▶ 録画開始'; }); // 初期化 updateUIForMode(modeSelect.value); renderGallery(); checkSecureContext(); // ページ終了時クリーンアップ window.addEventListener('beforeunload', stopStream);
カメラ撮影サイト(デバッグ強化)

カメラで撮影しよう!(デバッグ版)

デバッグ情報: 読み込み中...

撮影した写真

📁 ギャラリー

const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); const photo = document.getElementById('photo'); const recordedVideo = document.getElementById('recordedVideo'); const modeSelect = document.getElementById('mode'); const cameraSelect = document.getElementById('cameraSelect'); const startBtn = document.getElementById('start'); const fullscreenBtn = document.getElementById('fullscreen'); const captureBtn = document.getElementById('capture'); const recordBtn = document.getElementById('record'); const stopRecordBtn = document.getElementById('stopRecord'); const downloadBtn = document.getElementById('download'); const photoControls = document.getElementById('photoControls'); const videoControls = document.getElementById('videoControls'); const output = document.getElementById('output'); const gallery = document.getElementById('gallery'); const clearGalleryBtn = document.getElementById('clearGallery'); const modal = document.getElementById('modal'); const modalContent = document.getElementById('modalContent'); const closeModal = document.querySelector('.close'); const debugInfo = document.getElementById('debugInfo'); const ctx = canvas.getContext('2d'); let stream = null; let mediaRecorder = null; let recordedChunks = []; let currentFacingMode = 'user'; let galleryItems = JSON.parse(localStorage.getItem('cameraGallery') || '[]'); // セキュアコンテキストチェック(重要!) function checkSecureContext() { const isSecure = window.isSecureContext; const protocol = location.protocol; debugInfo.textContent = isSecure ? '✅ セキュア(許可画面が出るはず)' : '❌ 非セキュア! HTTPS/localhostに変更を'; if (!isSecure) { alert('非セキュア環境です! localhostサーバーでテストしてください。許可画面が出ません。'); } return isSecure; } // APIサポートチェック if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { alert('このブラウザはカメラをサポートしていません。最新のChrome/Safariをおすすめします。'); debugInfo.textContent = '❌ ブラウザ非対応'; throw new Error('Unsupported browser'); } // ギャラリー機能(前回と同じ、略) function renderGallery() { gallery.innerHTML = ''; galleryItems.forEach((item, index) => { const div = document.createElement('div'); div.className = 'gallery-item'; if (item.type === 'photo') { const img = document.createElement('img'); img.src = item.url; img.alt = `写真 ${index + 1}`; img. = () => openModal(img.src, 'photo'); div.appendChild(img); } else { const vid = document.createElement('video'); vid.src = item.url; vid.controls = false; vid.muted = true; vid. = () => openModal(vid.src, 'video'); div.appendChild(vid); } const delBtn = document.createElement('button'); delBtn.textContent = '削除'; delBtn.style.fontSize = '12px'; delBtn.style.marginTop = '5px'; delBtn. = (e) => { e.stopPropagation(); deleteItem(index); }; div.appendChild(delBtn); gallery.appendChild(div); }); } function saveGallery() { localStorage.setItem('cameraGallery', JSON.stringify(galleryItems)); } function addToGallery(url, type) { galleryItems.unshift({ url, type, timestamp: Date.now() }); if (galleryItems.length > 50) galleryItems = galleryItems.slice(0, 50); saveGallery(); renderGallery(); } function deleteItem(index) { galleryItems.splice(index, 1); saveGallery(); renderGallery(); } function openModal(src, type) { modalContent.innerHTML = ''; if (type === 'photo') { const img = document.createElement('img'); img.src = src; modalContent.appendChild(img); } else { const vid = document.createElement('video'); vid.src = src; vid.controls = true; vid.playsinline = true; modalContent.appendChild(vid); } modal.style.display = 'block'; } closeModal. = () => { modal.style.display = 'none'; }; window. = (e) => { if (e.target === modal) modal.style.display = 'none'; }; clearGalleryBtn. = () => { if (confirm('ギャラリーをクリアしますか?')) { galleryItems = []; saveGallery(); renderGallery(); } }; // モード切り替え modeSelect.addEventListener('change', (e) => { const mode = e.target.value; if (stream) stopStream(); updateUIForMode(mode); }); function updateUIForMode(mode) { if (mode === 'photo') { photoControls.style.display = 'block'; videoControls.style.display = 'none'; photo.style.display = 'block'; recordedVideo.style.display = 'none'; captureBtn.disabled = !stream; } else { photoControls.style.display = 'none'; videoControls.style.display = 'block'; photo.style.display = 'none'; recordedVideo.style.display = 'block'; recordBtn.disabled = !stream; } output.style.display = 'block'; downloadBtn.style.display = 'none'; } // カメラ選択 cameraSelect.addEventListener('change', (e) => { currentFacingMode = e.target.value; if (stream) { stopStream(); startCamera(); } }); // ストリーム停止 function stopStream() { if (stream) { stream.getTracks().forEach(track => track.stop()); stream = null; } startBtn.disabled = false; fullscreenBtn.disabled = true; recordBtn.disabled = true; captureBtn.disabled = true; stopRecordBtn.disabled = true; video.srcObject = null; } // カメラ開始(エラー詳細強化) async function startCamera() { try { if (!checkSecureContext()) { throw new Error('非セキュアコンテキスト'); } const constraints = { video: { facingMode: { ideal: currentFacingMode }, width: { ideal: 1280 }, height: { ideal: 720 } }, audio: false }; debugInfo.textContent = '🔄 許可を求め中...'; stream = await navigator.mediaDevices.getUserMedia(constraints); video.srcObject = stream; video.play(); startBtn.disabled = true; fullscreenBtn.disabled = false; debugInfo.textContent = '✅ カメラ接続成功!'; const mode = modeSelect.value; if (mode === 'photo') captureBtn.disabled = false; else recordBtn.disabled = false; } catch (err) { console.error('詳細エラー:', err); // コンソールに全ログ let errorMsg = `エラー: ${err.name} - ${err.message}`; if (err.name === 'NotAllowedError') errorMsg += '\n許可がブロック。ブラウザ設定で許可を!'; else if (err.name === 'NotFoundError') errorMsg += '\nカメラデバイスなし。'; else if (err.name === 'OverconstrainedError') errorMsg += '\n設定ミス。カメラ選択変更を。'; else if (err.name === 'NotReadableError') errorMsg += '\nカメラ使用中。アプリ閉じて。'; else errorMsg += '\nコンソール(F12)確認を!'; alert(errorMsg); debugInfo.textContent = `❌ ${err.name}: ${err.message}`; } } startBtn.addEventListener('click', startCamera); // フルスクリーン fullscreenBtn.addEventListener('click', () => { if (video.requestFullscreen) video.requestFullscreen(); else if (video.webkitRequestFullscreen) video.webkitRequestFullscreen(); }); // 写真撮影 captureBtn.addEventListener('click', () => { canvas.width = video.videoWidth || 640; canvas.height = video.videoHeight || 480; ctx.drawImage(video, 0, 0); const dataUrl = canvas.toDataURL('image/png'); photo.src = dataUrl; photo.style.display = 'block'; addToGallery(dataUrl, 'photo'); downloadBtn.href = dataUrl; downloadBtn.download = 'photo.png'; downloadBtn.textContent = '💾 写真をダウンロード'; downloadBtn.style.display = 'inline-block'; downloadBtn.style.fontSize = '18px'; downloadBtn.style.padding = '15px 25px'; downloadBtn.style.textDecoration = 'none'; downloadBtn.style.background = '#28a745'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '8px'; }); // 動画録画開始 recordBtn.addEventListener('click', () => { recordedChunks = []; mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' }); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) recordedChunks.push(e.data); }; mediaRecorder.onstop = () => { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); recordedVideo.src = url; recordedVideo.style.display = 'block'; addToGallery(url, 'video'); downloadBtn.href = url; downloadBtn.download = 'video.webm'; downloadBtn.textContent = '💾 動画をダウンロード'; downloadBtn.style.display = 'inline-block'; downloadBtn.style.fontSize = '18px'; downloadBtn.style.padding = '15px 25px'; downloadBtn.style.textDecoration = 'none'; downloadBtn.style.background = '#28a745'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '8px'; }; mediaRecorder.start(1000); recordBtn.disabled = true; stopRecordBtn.disabled = false; recordBtn.textContent = '⏸ 録画中...'; }); // 動画録画停止 stopRecordBtn.addEventListener('click', () => { if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); } recordBtn.disabled = false; stopRecordBtn.disabled = true; recordBtn.textContent = '▶ 録画開始'; }); // 初期化 updateUIForMode(modeSelect.value); renderGallery(); checkSecureContext(); // ページ読み込み時にチェック // ページ終了時クリーンアップ window.addEventListener('beforeunload', stopStream);
カメラ撮影サイト(ギャラリー付き)

カメラで撮影しよう!(ギャラリー付き)


撮影した写真

📁 ギャラリー

const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); const photo = document.getElementById('photo'); const recordedVideo = document.getElementById('recordedVideo'); const modeSelect = document.getElementById('mode'); const cameraSelect = document.getElementById('cameraSelect'); const startBtn = document.getElementById('start'); const fullscreenBtn = document.getElementById('fullscreen'); const captureBtn = document.getElementById('capture'); const recordBtn = document.getElementById('record'); const stopRecordBtn = document.getElementById('stopRecord'); const downloadBtn = document.getElementById('download'); const photoControls = document.getElementById('photoControls'); const videoControls = document.getElementById('videoControls'); const output = document.getElementById('output'); const gallery = document.getElementById('gallery'); const clearGalleryBtn = document.getElementById('clearGallery'); const modal = document.getElementById('modal'); const modalContent = document.getElementById('modalContent'); const closeModal = document.querySelector('.close'); const ctx = canvas.getContext('2d'); let stream = null; let mediaRecorder = null; let recordedChunks = []; let currentFacingMode = 'user'; let galleryItems = JSON.parse(localStorage.getItem('cameraGallery') || '[]'); // ローカル保存 // APIサポートチェック if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { alert('このブラウザはカメラをサポートしていません。最新のChrome/Safariをおすすめします。'); throw new Error('Unsupported browser'); } // ギャラリー初期表示 function renderGallery() { gallery.innerHTML = ''; galleryItems.forEach((item, index) => { const div = document.createElement('div'); div.className = 'gallery-item'; if (item.type === 'photo') { const img = document.createElement('img'); img.src = item.url; img.alt = `写真 ${index + 1}`; img. = () => openModal(img.src, 'photo'); div.appendChild(img); } else { const vid = document.createElement('video'); vid.src = item.url; vid.controls = false; vid.muted = true; vid. = () => openModal(vid.src, 'video'); div.appendChild(vid); } const delBtn = document.createElement('button'); delBtn.textContent = '削除'; delBtn. = (e) => { e.stopPropagation(); deleteItem(index); }; div.appendChild(delBtn); gallery.appendChild(div); }); } function saveGallery() { localStorage.setItem('cameraGallery', JSON.stringify(galleryItems)); } function addToGallery(url, type) { galleryItems.unshift({ url, type, timestamp: Date.now() }); // 新しいのを先頭に if (galleryItems.length > 50) galleryItems = galleryItems.slice(0, 50); // 最大50個 saveGallery(); renderGallery(); } function deleteItem(index) { galleryItems.splice(index, 1); saveGallery(); renderGallery(); } function openModal(src, type) { modalContent.innerHTML = ''; if (type === 'photo') { const img = document.createElement('img'); img.src = src; modalContent.appendChild(img); } else { const vid = document.createElement('video'); vid.src = src; vid.controls = true; vid.playsinline = true; modalContent.appendChild(vid); } modal.style.display = 'block'; } closeModal. = () => { modal.style.display = 'none'; }; window. = (e) => { if (e.target === modal) modal.style.display = 'none'; }; clearGalleryBtn. = () => { if (confirm('ギャラリーをクリアしますか?')) { galleryItems = []; saveGallery(); renderGallery(); } }; // モード切り替え modeSelect.addEventListener('change', (e) => { const mode = e.target.value; if (stream) stopStream(); updateUIForMode(mode); }); function updateUIForMode(mode) { if (mode === 'photo') { photoControls.style.display = 'block'; videoControls.style.display = 'none'; photo.style.display = 'block'; recordedVideo.style.display = 'none'; captureBtn.disabled = !stream; } else { photoControls.style.display = 'none'; videoControls.style.display = 'block'; photo.style.display = 'none'; recordedVideo.style.display = 'block'; recordBtn.disabled = !stream; } output.style.display = 'block'; downloadBtn.style.display = 'none'; } // カメラ選択 cameraSelect.addEventListener('change', (e) => { currentFacingMode = e.target.value; if (stream) { stopStream(); startCamera(); } }); // ストリーム停止 function stopStream() { if (stream) { stream.getTracks().forEach(track => track.stop()); stream = null; } startBtn.disabled = false; fullscreenBtn.disabled = true; recordBtn.disabled = true; captureBtn.disabled = true; stopRecordBtn.disabled = true; video.srcObject = null; } // カメラ開始(制約強化) async function startCamera() { try { const constraints = { video: { facingMode: { ideal: currentFacingMode }, // idealでフォールバック width: { ideal: 1280 }, height: { ideal: 720 } }, audio: false }; stream = await navigator.mediaDevices.getUserMedia(constraints); video.srcObject = stream; video.play(); startBtn.disabled = true; fullscreenBtn.disabled = false; const mode = modeSelect.value; if (mode === 'photo') captureBtn.disabled = false; else recordBtn.disabled = false; } catch (err) { console.error('カメラ開始エラー:', err); let errorMsg = `エラー: ${err.name} - ${err.message}`; if (err.name === 'NotAllowedError') errorMsg += '\nカメラ許可をブラウザでオンにしてください。'; else if (err.name === 'OverconstrainedError') errorMsg += '\nカメラ設定が合わない。選択を変更して再試行。'; alert(errorMsg); } } startBtn.addEventListener('click', startCamera); // フルスクリーン fullscreenBtn.addEventListener('click', () => { if (video.requestFullscreen) video.requestFullscreen(); else if (video.webkitRequestFullscreen) video.webkitRequestFullscreen(); }); // 写真撮影 captureBtn.addEventListener('click', () => { canvas.width = video.videoWidth || 640; canvas.height = video.videoHeight || 480; ctx.drawImage(video, 0, 0); const dataUrl = canvas.toDataURL('image/png'); photo.src = dataUrl; photo.style.display = 'block'; addToGallery(dataUrl, 'photo'); // ギャラリー追加 downloadBtn.href = dataUrl; downloadBtn.download = 'photo.png'; downloadBtn.textContent = '💾 写真をダウンロード'; downloadBtn.style.display = 'inline-block'; downloadBtn.style.fontSize = '18px'; downloadBtn.style.padding = '15px 25px'; downloadBtn.style.textDecoration = 'none'; downloadBtn.style.background = '#28a745'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '8px'; }); // 動画録画開始 recordBtn.addEventListener('click', () => { recordedChunks = []; mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' }); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) recordedChunks.push(e.data); }; mediaRecorder.onstop = () => { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); recordedVideo.src = url; recordedVideo.style.display = 'block'; addToGallery(url, 'video'); // ギャラリー追加 downloadBtn.href = url; downloadBtn.download = 'video.webm'; downloadBtn.textContent = '💾 動画をダウンロード'; downloadBtn.style.display = 'inline-block'; downloadBtn.style.fontSize = '18px'; downloadBtn.style.padding = '15px 25px'; downloadBtn.style.textDecoration = 'none'; downloadBtn.style.background = '#28a745'; downloadBtn.style.color = 'white'; downloadBtn.style.borderRadius = '8px'; }; mediaRecorder.start(1000); recordBtn.disabled = true; stopRecordBtn.disabled = false; recordBtn.textContent = '⏸ 録画中...'; }); // 動画録画停止 stopRecordBtn.addEventListener('click', () => { if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); } recordBtn.disabled = false; stopRecordBtn.disabled = true; recordBtn.textContent = '▶ 録画開始'; }); // 初期化 updateUIForMode(modeSelect.value); renderGallery(); // ページ終了時クリーンアップ window.addEventListener('beforeunload', stopStream);
カメラ撮影サイト(動画・写真・カメラ選択)

カメラで撮影しよう!(動画・写真)



撮影した写真

const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); const photo = document.getElementById('photo'); const recordedVideo = document.getElementById('recordedVideo'); const modeSelect = document.getElementById('mode'); const cameraSelect = document.getElementById('cameraSelect'); const startBtn = document.getElementById('start'); const captureBtn = document.getElementById('capture'); const recordBtn = document.getElementById('record'); const stopRecordBtn = document.getElementById('stopRecord'); const downloadBtn = document.getElementById('download'); const photoControls = document.getElementById('photoControls'); const videoControls = document.getElementById('videoControls'); const output = document.getElementById('output'); const ctx = canvas.getContext('2d'); let stream = null; let mediaRecorder = null; let recordedChunks = []; let currentDeviceId = null; // APIサポートチェック if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { alert('このブラウザはカメラをサポートしていません。Chrome/Firefoxをおすすめします。'); throw new Error('Unsupported browser'); } // モード切り替え modeSelect.addEventListener('change', (e) => { const mode = e.target.value; if (stream) stopStream(); // ストリームを止めてリセット updateUIForMode(mode); }); function updateUIForMode(mode) { if (mode === 'photo') { photoControls.style.display = 'block'; videoControls.style.display = 'none'; photo.style.display = 'block'; recordedVideo.style.display = 'none'; output.style.display = 'block'; downloadBtn.style.display = 'none'; captureBtn.disabled = !stream; } else { photoControls.style.display = 'none'; videoControls.style.display = 'block'; photo.style.display = 'none'; recordedVideo.style.display = 'block'; output.style.display = 'block'; downloadBtn.style.display = 'none'; recordBtn.disabled = !stream; } } // カメラデバイスリスト更新(許可後) async function updateDeviceList() { try { const devices = await navigator.mediaDevices.enumerateDevices(); const videoDevices = devices.filter(device => device.kind === 'videoinput'); cameraSelect.innerHTML = ''; videoDevices.forEach((device) => { const option = document.createElement('option'); option.value = device.deviceId; option.text = device.label || `カメラ ${device.deviceId ? '(詳細不明)' : ''}`; cameraSelect.appendChild(option); }); if (videoDevices.length === 0) { cameraSelect.innerHTML += ''; } } catch (err) { console.error('デバイスリスト更新エラー:', err); } } // カメラ選択変更 cameraSelect.addEventListener('change', (e) => { currentDeviceId = e.target.value; if (stream) { stopStream(); startCamera(); // 自動再開始 } }); // ストリーム停止 function stopStream() { if (stream) { stream.getTracks().forEach(track => track.stop()); stream = null; } startBtn.disabled = false; recordBtn.disabled = true; captureBtn.disabled = true; stopRecordBtn.disabled = true; video.srcObject = null; updateDeviceList(); // リストをクリア } // カメラ開始 async function startCamera() { try { const constraints = { video: currentDeviceId ? { deviceId: { exact: currentDeviceId } } : { facingMode: 'user' } // デフォルト: フロントカメラ }; stream = await navigator.mediaDevices.getUserMedia(constraints); video.srcObject = stream; video.play(); startBtn.disabled = true; await updateDeviceList(); // 許可後にリスト更新 const mode = modeSelect.value; if (mode === 'photo') captureBtn.disabled = false; else recordBtn.disabled = false; } catch (err) { console.error('カメラ開始エラー:', err); let errorMsg = `エラー: ${err.name} - ${err.message}`; if (err.name === 'NotAllowedError') errorMsg += '\n許可をブロックしています。ブラウザ設定で許可してください。'; else if (err.name === 'NotFoundError') errorMsg += '\nカメラデバイスが見つかりません。他のアプリを閉じてください。'; else if (err.name === 'NotReadableError') errorMsg += '\nカメラが使用中です。他のアプリを停止してください。'; alert(errorMsg); } } startBtn.addEventListener('click', startCamera); // 写真撮影 captureBtn.addEventListener('click', () => { ctx.drawImage(video, 0, 0, 640, 480); const dataUrl = canvas.toDataURL('image/png'); photo.src = dataUrl; photo.style.display = 'block'; downloadBtn.href = dataUrl; downloadBtn.download = 'photo.png'; downloadBtn.textContent = '💾 写真をダウンロード'; downloadBtn.style.display = 'inline-block'; }); // 動画録画開始 recordBtn.addEventListener('click', () => { recordedChunks = []; mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' }); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) recordedChunks.push(e.data); }; mediaRecorder.onstop = () => { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); recordedVideo.src = url; recordedVideo.style.display = 'block'; downloadBtn.href = url; downloadBtn.download = 'video.webm'; downloadBtn.textContent = '💾 動画をダウンロード'; downloadBtn.style.display = 'inline-block'; }; mediaRecorder.start(1000); // 1秒ごとにチャンク recordBtn.disabled = true; stopRecordBtn.disabled = false; recordBtn.textContent = '⏸ 録画中...'; }); // 動画録画停止 stopRecordBtn.addEventListener('click', () => { if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); } recordBtn.disabled = false; stopRecordBtn.disabled = true; recordBtn.textContent = '▶ 録画開始'; }); // 初期UI設定 updateUIForMode(modeSelect.value); // ページ終了時クリーンアップ window.addEventListener('beforeunload', stopStream);
startBtn.addEventListener('click', async () => { try { if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { throw new Error('このブラウザはカメラAPIをサポートしていません'); } await enumerateDevices(); const constraints = { video: { deviceId: { exact: currentDeviceId || { exact: 'default' } }, facingMode: 'user' // スマホのフロントカメラ優先 } }; stream = await navigator.mediaDevices.getUserMedia(constraints); // ... 続きは同じ } catch (err) { console.error('詳細エラー:', err); // コンソールにログ出力 alert('カメラアクセスに失敗しました: ' + err.name + ' - ' + err.message); } });
カメラ撮影サイト(動画・写真)

カメラで撮影しよう!(動画・写真)



撮影した写真
const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); const photo = document.getElementById('photo'); const recordedVideo = document.getElementById('recordedVideo'); const modeSelect = document.getElementById('mode'); const cameraSelect = document.getElementById('cameraSelect'); const startBtn = document.getElementById('start'); const captureBtn = document.getElementById('capture'); const recordBtn = document.getElementById('record'); const stopRecordBtn = document.getElementById('stopRecord'); const downloadBtn = document.getElementById('download'); const photoControls = document.getElementById('photoControls'); const videoControls = document.getElementById('videoControls'); const ctx = canvas.getContext('2d'); let stream = null; let mediaRecorder = null; let recordedChunks = []; let currentDeviceId = null; // モード切り替え modeSelect.addEventListener('change', (e) => { const mode = e.target.value; if (mode === 'photo') { photoControls.style.display = 'block'; videoControls.style.display = 'none'; photo.style.display = 'block'; recordedVideo.style.display = 'none'; downloadBtn.style.display = 'none'; } else { photoControls.style.display = 'none'; videoControls.style.display = 'block'; photo.style.display = 'none'; recordedVideo.style.display = 'block'; downloadBtn.style.display = 'block'; } // 再開始が必要な場合、ストリームをリセット if (stream) stopStream(); }); // カメラデバイスリスト取得 async function enumerateDevices() { try { const devices = await navigator.mediaDevices.enumerateDevices(); const videoDevices = devices.filter(device => device.kind === 'videoinput'); cameraSelect.innerHTML = ''; videoDevices.forEach((device, index) => { const option = document.createElement('option'); option.value = device.deviceId; option.text = device.label || `カメラ ${index + 1}`; cameraSelect.appendChild(option); }); if (videoDevices.length > 0) { currentDeviceId = videoDevices[0].deviceId; // デフォルトで最初のデバイス } } catch (err) { console.error('デバイス取得エラー:', err); } } // カメラ選択変更 cameraSelect.addEventListener('change', (e) => { currentDeviceId = e.target.value; if (stream) stopStream(); }); // ストリーム停止 function stopStream() { if (stream) { stream.getTracks().forEach(track => track.stop()); stream = null; } startBtn.disabled = false; if (modeSelect.value === 'photo') captureBtn.disabled = true; else recordBtn.disabled = true; stopRecordBtn.disabled = true; } // カメラ開始 startBtn.addEventListener('click', async () => { try { await enumerateDevices(); // デバイスリスト更新(許可後) const constraints = { video: { deviceId: { exact: currentDeviceId || { exact: 'default' } } } }; stream = await navigator.mediaDevices.getUserMedia(constraints); video.srcObject = stream; startBtn.disabled = true; if (modeSelect.value === 'photo') captureBtn.disabled = false; else recordBtn.disabled = false; video.play(); } catch (err) { alert('カメラアクセスに失敗しました: ' + err.message); } }); // 写真撮影 captureBtn.addEventListener('click', () => { ctx.drawImage(video, 0, 0, 640, 480); photo.src = canvas.toDataURL('image/png'); photo.style.display = 'block'; downloadBtn.href = photo.src; downloadBtn.download = 'photo.png'; downloadBtn.style.display = 'inline'; }); // 動画録画開始 recordBtn.addEventListener('click', () => { recordedChunks = []; mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm;codecs=vp9' }); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) recordedChunks.push(e.data); }; mediaRecorder.onstop = () => { const blob = new Blob(recordedChunks, { type: 'video/webm' }); recordedVideo.src = URL.createObjectURL(blob); downloadBtn.href = recordedVideo.src; downloadBtn.download = 'video.webm'; downloadBtn.style.display = 'inline'; }; mediaRecorder.start(); recordBtn.disabled = true; stopRecordBtn.disabled = false; }); // 動画録画停止 stopRecordBtn.addEventListener('click', () => { mediaRecorder.stop(); recordBtn.disabled = false; stopRecordBtn.disabled = true; }); // ダウンロード(共通) downloadBtn.addEventListener('click', (e) => { // 自動ダウンロードは上記のhref/downloadで処理 }); // ページ終了時にクリーンアップ window.addEventListener('beforeunload', () => { stopStream(); if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); } }); // 初期デバイスリスト取得(許可前にラベルは空になる場合あり) enumerateDevices();

小さな工事から承ります、お気軽にご相談ください!

住まいを長持ちさせたい。外観を美しくしたい。冬寒く、夏暑い環境を改善したい。樋の変形や破損を修理したい。雨漏りを修理したい。屋根材の一部がズレたり割れたりしているので修理したい。など様々なご要望に対応いたします。

耐用年数に達した部分の取り替えや壊れた箇所の修理やリフォームなどは早目にご相談ください!

サンプル会社の特長

担当者が一人なので安心

1人の担当営業者がお見積りから現場の施工管理までをワンストップで行うので安心できます。施工の要望などを誰に伝えたらよいのかわからなくなる心配もありません。また、現場の知識豊富なスタッフが言われたままの注文を受けて施工するだけではなく、お客様のお住まいの現状やご要望を伺ったうえで、先を見据えたご提案も可能です。

最短で3日後から工事可能

施工日は比較的融通がきき、最短でご契約の3日後から施工可能です。 ベテラン工事スタッフによる連携プレイで瞬時に現在の状態を把握し、スムーズな段取りで工事を行います。リフォーム工事の内容や規模にもよりますが、工事期間は1週間以内で施工完了。早ければ2、3日で仕上がります。 雨漏り工事など、お急ぎのお客様も安心してお任せください。 

最長15年の長期保証

工事を行っていただいたお客様には、最長15年の工事保証を行っております。リフォーム工事が原因で既存部分に不具合が発生した場合、または工事そのものに不具合がある場合にお客様に不利益が起こらないようにする保証制度です。

実績紹介

お知らせ

0000/00/00  採用情報を掲載しました。募集要項を必ずご確認の上ご応募ください。


0000/00/00  代表挨拶を更新いたしました。


0000/00/00  施工実例、お客様の声を掲載いたしました。


0000/00/00  12/30 18:00で年内の営業を終了いたします。年始は1/4 10:00より開始します。


0000/00/00  ホームページを公開いたしました。今後ともよろしくお願いいたします。


会社案内

会社名サンプル会社
所在地00-0000 東京都東京都渋谷区神宮前3-42-2
電話番号00-0000-0000
営業時間・定休日00:00~00:00(○曜日休業)
最寄り駅○○○線「○○○駅」より徒歩○○分
○○○線「○○○駅」より徒歩○○分