見出し画像

コピペするだけ!簡単「渋滞タイムロス&時間損失ナビ」

連休と言えば帰省ラッシュ。

お出かけされるかた、されているかた、渋滞にはまってもイライラすることなく、安全にお出かけくださいね。

そんな渋滞の中、この時間があれば何をどのくらいできただろうかなど、冷静に見極めてみたら案外楽しいかもしれません。


読ませて頂いた記事をマガジンに追加させて頂いております。

伺った際にはマガジンへの登録をさせて頂いていきますが、それはやめてほしいなどありましたら、DM / コメントで一言頂けましたら幸いです😊


ブックマークに置いとくだけ!

コピペするだけの簡単小道具!

Geminiで簡単!ツール作成!

一発作成プロンプトも紹介!


渋滞時の暇潰し、運転手さんはどうしようもないけど、同乗者さんができる何かはないものだろうか。
今どきゲームや音楽、動画だって楽しめちゃうんだけどねー。
をGeminiさんにぶん投げた。

⭐️ 今日のツールはこんなものだよ!


渋滞の長さと!

大まかな速度を選択!

年齢をスライダーで設定すると!

映画が何本見れたのか!

カップラーメンを何回作れたのか!

脳内反省会が何回できたのか!

ロス時間と余命から計算した損失率とともに!

全て計算して確認できる!


🛠️ 使い方(スマホ版)

1. 適当なページをブックマークする

まずは、今見ているこのページなど、何でもいいので一度ブックマークに登録します。

2. 「編集」を開く

ブックマークバーにある今作ったブックマークを長押しして、「編集」を選択します。

3. 内容を書き換える

表示された設定画面で、以下の2箇所を変更して保存します。

  • 名前:(自分が分かりやすい名前)

  • URL:もともと入っているURLをすべて消して、コードを貼り付ける

ブックマークを押すだけ簡単!

💡 Androidをご使用の場合、以下の記事をご確認ください!


📋 これを貼ります!

javascript:(function(){ var w = window.open('', '_blank'); if(!w) return; var d = w.document; var head = d.head || d.getElementsByTagName('head')[0] || d.createElement('head'); var body = d.body || d.getElementsByTagName('body')[0] || d.createElement('body'); if(!d.head) d.documentElement.appendChild(head); if(!d.body) d.documentElement.appendChild(body); var titleTag = d.createElement('title'); titleTag.textContent = '🚗💨 渋滞タイムロス&時間損失ナビ'; head.appendChild(titleTag); body.style.backgroundColor = '#0f172a'; body.style.color = '#f8fafc'; body.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif'; body.style.margin = '0'; body.style.padding = '24px 16px'; body.style.minHeight = '100vh'; body.style.display = 'flex'; body.style.justifyContent = 'center'; body.style.alignItems = 'flex-start'; body.style.boxSizing = 'border-box'; function playBeep() { try { var AudioCtx = w.AudioContext || w.webkitAudioContext; if (!AudioCtx) return; var ctx = new AudioCtx(); var osc = ctx.createOscillator(); var gain = ctx.createGain(); osc.type = 'sine'; osc.frequency.setValueAtTime(880, ctx.currentTime); osc.frequency.setValueAtTime(1760, ctx.currentTime + 0.05); gain.gain.setValueAtTime(0.08, ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.12); osc.connect(gain); gain.connect(ctx.destination); osc.start(); osc.stop(ctx.currentTime + 0.12); } catch(e){} } var card = d.createElement('div'); card.style.backgroundColor = '#1e293b'; card.style.border = '1px solid #334155'; card.style.borderRadius = '16px'; card.style.width = '100%'; card.style.maxWidth = '700px'; card.style.padding = '24px'; card.style.boxSizing = 'border-box'; card.style.boxShadow = '0 10px 25px -5px rgba(0, 0, 0, 0.5), 0 8px 10px -6px rgba(0, 0, 0, 0.5)'; body.appendChild(card); var header = d.createElement('div'); header.style.marginBottom = '20px'; header.style.textAlign = 'center'; card.appendChild(header); var title = d.createElement('h1'); title.textContent = '🚗💨 渋滞タイムロス&時間損失ナビ'; title.style.color = '#38bdf8'; title.style.fontSize = '20px'; title.style.fontWeight = 'bold'; title.style.margin = '0 0 6px 0'; header.appendChild(title); var sub = d.createElement('p'); sub.textContent = 'お盆のUターンラッシュで失われる可処分時間を大真面目に可視化'; sub.style.fontSize = '13px'; sub.style.color = '#94a3b8'; sub.style.margin = '0'; header.appendChild(sub); var state = { distance: 15, speed: 10, age: 35 }; function createSection(labelTxt) { var sec = d.createElement('div'); sec.style.marginBottom = '18px'; var lbl = d.createElement('label'); lbl.style.display = 'block'; lbl.style.fontSize = '14px'; lbl.style.color = '#cbd5e1'; lbl.style.marginBottom = '8px'; lbl.style.fontWeight = '600'; lbl.textContent = labelTxt; sec.appendChild(lbl); return { sec: sec, lbl: lbl }; } /* 距離スライダー */ var distSec = createSection('渋滞の長さ: 15 km'); card.appendChild(distSec.sec); var distRange = d.createElement('input'); distRange.type = 'range'; distRange.min = '1'; distRange.max = '100'; distRange.value = '15'; distRange.style.width = '100%'; distRange.style.cursor = 'pointer'; distRange.style.accentColor = '#38bdf8'; distSec.sec.appendChild(distRange); /* 通過速度選択ボタン */ var spdSec = createSection('通過速度'); card.appendChild(spdSec.sec); var btnGroup = d.createElement('div'); btnGroup.style.display = 'grid'; btnGroup.style.gridTemplateColumns = 'repeat(3, 1fr)'; btnGroup.style.gap = '8px'; spdSec.sec.appendChild(btnGroup); var speedOptions = [ { label: '🐢 10km/h', val: 10 }, { label: '🚶 5km/h', val: 5 }, { label: '🛑 1km/h', val: 1 } ]; var speedButtons = []; speedOptions.forEach(function(opt) { var btn = d.createElement('button'); btn.type = 'button'; btn.textContent = opt.label; btn.style.padding = '10px 4px'; btn.style.borderRadius = '8px'; btn.style.border = '1px solid #475569'; btn.style.backgroundColor = (opt.val === state.speed) ? '#0284c7' : '#334155'; btn.style.color = '#ffffff'; btn.style.fontSize = '13px'; btn.style.fontWeight = '600'; btn.style.cursor = 'pointer'; btn.style.transition = 'all 0.2s'; btn.onclick = function() { state.speed = opt.val; speedButtons.forEach(function(b) { b.btn.style.backgroundColor = (b.val === state.speed) ? '#0284c7' : '#334155'; b.btn.style.borderColor = (b.val === state.speed) ? '#38bdf8' : '#475569'; }); playBeep(); updateCalc(); }; speedButtons.push({ btn: btn, val: opt.val }); btnGroup.appendChild(btn); }); /* 年齢スライダー */ var ageSec = createSection('あなたの年齢: 35 歳(80歳までの残り時間基準)'); card.appendChild(ageSec.sec); var ageRange = d.createElement('input'); ageRange.type = 'range'; ageRange.min = '10'; ageRange.max = '79'; ageRange.value = '35'; ageRange.style.width = '100%'; ageRange.style.cursor = 'pointer'; ageRange.style.accentColor = '#38bdf8'; ageSec.sec.appendChild(ageRange); /* 結果表示パネル */ var resultBox = d.createElement('div'); resultBox.style.backgroundColor = '#0b1329'; resultBox.style.border = '1px solid #1e293b'; resultBox.style.borderRadius = '12px'; resultBox.style.padding = '18px'; resultBox.style.marginTop = '20px'; card.appendChild(resultBox); var resGrid = d.createElement('div'); resGrid.style.display = 'grid'; resGrid.style.gridTemplateColumns = '1fr 1fr'; resGrid.style.gap = '12px'; resGrid.style.marginBottom = '16px'; resultBox.appendChild(resGrid); var lossBox = d.createElement('div'); lossBox.style.backgroundColor = '#1e293b'; lossBox.style.padding = '12px'; lossBox.style.borderRadius = '8px'; lossBox.style.textAlign = 'center'; var lossTitle = d.createElement('div'); lossTitle.textContent = '純粋なタイムロス'; lossTitle.style.fontSize = '12px'; lossTitle.style.color = '#94a3b8'; var lossValue = d.createElement('div'); lossValue.style.color = '#ef4444'; lossValue.style.fontSize = '28px'; lossValue.style.fontWeight = 'bold'; lossValue.style.marginTop = '4px'; lossBox.appendChild(lossTitle); lossBox.appendChild(lossValue); resGrid.appendChild(lossBox); var rateBox = d.createElement('div'); rateBox.style.backgroundColor = '#1e293b'; rateBox.style.padding = '12px'; rateBox.style.borderRadius = '8px'; rateBox.style.textAlign = 'center'; var rateTitle = d.createElement('div'); rateTitle.textContent = '余命可処分時間 損失率'; rateTitle.style.fontSize = '12px'; rateTitle.style.color = '#94a3b8'; var rateValue = d.createElement('div'); rateValue.style.color = '#f59e0b'; rateValue.style.fontSize = '22px'; rateValue.style.fontWeight = 'bold'; rateValue.style.marginTop = '8px'; rateBox.appendChild(rateTitle); rateBox.appendChild(rateValue); resGrid.appendChild(rateBox); /* 換算ボックス */ var convSec = d.createElement('div'); convSec.style.backgroundColor = '#1e293b'; convSec.style.padding = '12px'; convSec.style.borderRadius = '8px'; convSec.style.marginBottom = '16px'; resultBox.appendChild(convSec); var convTitle = d.createElement('div'); convTitle.textContent = '📊 ロス時間の等価換算'; convTitle.style.fontSize = '12px'; convTitle.style.color = '#94a3b8'; convTitle.style.marginBottom = '8px'; convSec.appendChild(convTitle); var convList = d.createElement('div'); convList.style.display = 'grid'; convList.style.gridTemplateColumns = 'repeat(3, 1fr)'; convList.style.gap = '8px'; convList.style.fontSize = '13px'; convList.style.textAlign = 'center'; convSec.appendChild(convList); var convMovie = d.createElement('div'); convMovie.style.backgroundColor = '#0f172a'; convMovie.style.padding = '8px 4px'; convMovie.style.borderRadius = '6px'; var convRamen = d.createElement('div'); convRamen.style.backgroundColor = '#0f172a'; convRamen.style.padding = '8px 4px'; convRamen.style.borderRadius = '6px'; var convReflect = d.createElement('div'); convReflect.style.backgroundColor = '#0f172a'; convReflect.style.padding = '8px 4px'; convReflect.style.borderRadius = '6px'; convList.appendChild(convMovie); convList.appendChild(convRamen); convList.appendChild(convReflect); /* コメント枠 */ var commentBox = d.createElement('div'); commentBox.style.padding = '12px 14px'; commentBox.style.borderRadius = '8px'; commentBox.style.backgroundColor = '#1e293b'; commentBox.style.borderLeft = '4px solid #38bdf8'; commentBox.style.fontSize = '13px'; commentBox.style.lineHeight = '1.5'; commentBox.style.color = '#e2e8f0'; resultBox.appendChild(commentBox); function updateCalc() { var dist = parseFloat(state.distance); var spd = parseFloat(state.speed); var age = parseFloat(state.age); var lossHours = (dist / spd) - (dist / 100); if (lossHours < 0) lossHours = 0; var remainingLifeHours = (80 - age) * 8760; var lossPct = remainingLifeHours > 0 ? (lossHours / remainingLifeHours) * 100 : 0; var hoursInt = Math.floor(lossHours); var minsInt = Math.round((lossHours - hoursInt) * 60); var lossStr = ''; if (hoursInt > 0) { lossStr = hoursInt + '時間 ' + minsInt + '分'; } else { lossStr = minsInt + '分 (' + lossHours.toFixed(2) + 'h)'; } lossValue.textContent = lossStr; rateValue.textContent = lossPct.toFixed(6) + ' %'; var movies = (lossHours / 2).toFixed(1); var ramen = Math.round(lossHours * 20); convMovie.textContent = '🎬 映画 ' + movies + ' 本分'; convRamen.textContent = '🍜 ラーメン ' + ramen + ' 杯分'; convReflect.textContent = '🧘 反省 ∞ 回'; if (lossHours >= 3) { commentBox.textContent = '【大渋滞】貴重な自由時間が削り取られています'; commentBox.style.borderLeftColor = '#ef4444'; } else if (lossHours >= 1) { commentBox.textContent = '映画が1本観終わる損失です'; commentBox.style.borderLeftColor = '#f59e0b'; } else { commentBox.textContent = '軽微な損失です。安全運転で。'; commentBox.style.borderLeftColor = '#10b981'; } } distRange.oninput = function() { state.distance = distRange.value; distSec.lbl.textContent = '渋滞の長さ: ' + state.distance + ' km'; updateCalc(); }; distRange.onchange = function() { playBeep(); }; ageRange.oninput = function() { state.age = ageRange.value; ageSec.lbl.textContent = 'あなたの年齢: ' + state.age + ' 歳(80歳までの残り時間基準)'; updateCalc(); }; ageRange.onchange = function() { playBeep(); }; updateCalc();})();void(0);

⚙️ 一発作成プロンプト!

お盆のUターンラッシュ(8月15日〜16日)を題材に、渋滞で失われた時間と可処分時間の損失割合を大真面目に計算するツール「🚗💨 渋滞タイムロス&時間損失ナビ」を、新規タブ(別タブ)で起動するブックマークレットを作成してください。

一時保存や外部通信、実行元ページへのDOM追加は禁止とし、完全なES5/ES6互換構文で構成してください。

【TrustedHTML回避 & 新規タブ生成の絶対ルール】
1. innerHTML, outerHTML, document.write は禁止。d.createElement と textContent のみで全UIを構築してください。
2. 新タブ初期化時は以下を使用すること:
   var w = window.open('', '_blank');
   if(!w) return;
   var d = w.document;
   var head = d.head || d.getElementsByTagName('head')[0] || d.createElement('head');
   var body = d.body || d.getElementsByTagName('body')[0] || d.createElement('body');
   if(!d.head) d.documentElement.appendChild(head);
   if(!d.body) d.documentElement.appendChild(body);
3. テンプレートリテラル(バックティック)は使わず、シングルクォート(')文字列結合のみを使用してください。

【計算ロジック】
- 入力:
  ・ 渋滞の長さ(1〜100km、初期値15km)
  ・ 通過速度[🐢 10km/h / 🚶 5km/h / 🛑 1km/h](初期値10km/h)
  ・ 年齢(10〜79歳、初期値35歳)
- 計算:
  ・ ロス時間(h) = (距離 / 速度) - (距離 / 100)
  ・ 人生時間損失率(%) = (ロス時間 / ((80 - 年齢) * 8760)) * 100
  ・ 換算: 映画(ロス/2本)、ラーメン(ロス*20杯)、反省(∞回)
  ・ コメント: 3h以上は「【大渋滞】貴重な自由時間が削り取られています」、1h以上は「映画が1本観終わる損失です」、1h未満は「軽微な損失です。安全運転で。」

【UIデザイン】
・ 全体背景: #0f172a, カード: #1e293b (角丸16px, 幅最大700px, #334155枠線)
・ タイトル: 🚗💨 渋滞タイムロス&時間損失ナビ (#38bdf8 / 20px)
・ スライダー(距離・年齢)、速度切替ボタン、損失時間(#ef4444 / 28px)、時間損失率(#f59e0b / 22px)、換算表示、コメント枠を配置。
・ Web Audio API による操作時ビープ音(ピピッ)を実装。

【出力形式】
解説文は含めず、全体を javascript:(function(){ ... })();void(0); の単一コードブロックのみで出力してください。

この記事について!

今更ながら、Gemini 3分クッキング記事について注意点など|へろん


📖 エッセイ

どうやら私は、ひとりだけ別の世界に住んでいるようだ (全4話)


📖 短編小説


💡 PR記事を書かせて頂いています!


❓ 何でもどうぞ!答えられるものは全て答えます!

設置はお済みですか?図らずも人の庭でnote質問箱を試す!|へろん


メンバーシップ始めました!

まだ手探りですが、ご要望/無茶振り/質問、可能な限りお受けします!


参加させて頂いています!是非チェックしてみてください😆


✏️ 有料ツールに挑戦中!

OBS Studio用リモコン | OBS画面を前面に出さずに操作できます!


🧰 小道具すべて、こちらに置きました!


☕ サイトマップあります!

いいなと思ったら応援しよう!