4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

電子レンジのワット数変換ツールを作ってみよう

Posted at

はじめに

8月も終わりとはいえ、まだまだ暑い日が続きますね!
キッチンに立って料理するとなるとさらに暑くなるので、最近は自炊が面倒くさく、コンビニのお弁当やお惣菜に頼りがちになっています💦

ただそこでいつも困るのが、電子レンジの加熱時間!

パッケージには 「500Wで4分」「600Wで3分30秒」 など時間が書かれていますが、記載のワット数以外で温めたいとき、何分で温めればいいかな?と毎回スマホを取り出して電卓で計算しています。
これが意外と面倒で、ちょっとしたことですが地味にストレスになっていました…。

そこでもっと楽に計算するために、電子レンジのワット数変換ツール「あっためチェッカー」を作成しました!

見た目はこんな感じです。
あっためチェッカーpc.png
あっためチェッカーsp.png

せっかくなら自分好みに仕上げようと思い、黄色・ピンク・青など好きな色を使ったりイラストを描いたりして可愛く仕上げました。
そして、実はPCの時は電子レンジ風の配置にしているのも密かなこだわりです✨

できること

1.ワット数変換
2.秒数の端数処理選択(四捨五入/短め/長め)
3.保存機能(上限20件)
4.削除機能
5.BGMとSEのミュート

今回はこちらの機能の中から、保存機能と削除機能をどう実装したか簡単な解説をします!

計算ロジック

まず、そもそもどのように計算しているかですが、公式はシンプルです!

const raw = t1 * (w1 / w2);

w1→元のワット数
t1→入力時間(秒)
w2→変換したいワット数
raw→変換後の時間(秒)


「500Wで4分10秒(=250秒)」を「700W」に変換すると、
250 × (500 / 700) ≒ 178秒 → 約3分
となります!

なお端数処理は、「切り捨て」「切り上げ」「四捨五入」を選択できるようにしています。

保存機能の仕組み

保存モーダルの表示

「保存」ボタンを押すと savePreset() が呼ばれ、入力内容をチェック!
そして保存名を入力できるモーダルを表示します。

function savePreset(){
  const arr = JSON.parse(localStorage.getItem(LS_KEY) || '[]');
  if(arr.length >= 20){
    // 保存上限チェック
    $("save-limit-modal").style.display = "flex";
    return;
  }
  // 入力チェック
  const w1 = Number($('w1').value);
  const w2 = Number($('w2').value);
  const m1 = Number($('m1').value||0);
  const s1 = Number($('s1').value||0);
  if(!w1 || !w2 || (m1===0 && s1===0)){
    showToast("保存前に数値を入力してください");
    return;
  }
  // デフォルト名をセット
  $("save-name").value = `${w1}W→${w2}W ${m1}${pad(s1)}秒`;
  $("save-modal").style.display = "flex";
}

解説
無限に溜まらないように、最大20件までの保存に制御。
さらに入力値が未設定だと保存ができないよう「保存前に数値を入力してください」と、表示させる。
保存時には自由に名前を付けられるが、「500W→700W 4分10秒」などユーザーの入力した数値によって、デフォルトで名前を自動入力しUXを向上させる。

保存の実行

保存ボタンを押すと localStorage にオブジェクトを追加します。

$("save-confirm").addEventListener("click", ()=>{
  const name = $("save-name").value.trim();
  if(!name) return;

  const arrRaw = JSON.parse(localStorage.getItem(LS_KEY) || '[]');
  const arr = arrRaw.map(item => typeof item === 'string' ? { label: item } : item );

  const preset = {
    label: name,
    w1: Number($('w1').value),
    w2: Number($('w2').value),
    m1: Number($('m1').value||0),
    s1: Number($('s1').value||0),
    rounding: $('rounding').value,
    margin: Number($('margin').value||0),
  };

  if (arr.length >= 20) {
    $("save-modal").style.display = "none";
    $("save-limit-modal").style.display = "flex";
    return;
  }

  arr.unshift(preset);
  localStorage.setItem(LS_KEY, JSON.stringify(arr));

  $("save-modal").style.display = "none";
  renderPresets(arr);
  showToast("保存しました!");
});

解説
保存データはオブジェクト化し、ワット数・分・秒・端数の処理なども一緒に保持。
最大件数を超えたら保存を拒否する。
保存後は renderPresets() を呼び出して即時反映。
成功メッセージをトーストで表示して、ユーザーが保存に気づけるように工夫。

削除機能の仕組み

削除モーダル

続いては、削除機能の仕組みです!
削除は、どれか1つがチェックされたら削除ボタンを押せるようにしています。

$("delete").addEventListener("click", () => {
  const arrRaw = JSON.parse(localStorage.getItem(LS_KEY) || "[]");
  const arr = arrRaw.map(item => typeof item === 'string' ? { label: item } : item );
  const listBox = $("delete-list");
  const deleteBtn = $("delete-confirm");
  listBox.innerHTML = "";
  deleteBtn.disabled = true;

  if (!arr.length) {
    listBox.innerHTML = "<p>保存されたレシピはありません。</p>";
  } else {
    arr.forEach((p, i) => {
      const lbl = document.createElement("label");
      lbl.innerHTML = `<input type="checkbox" value="${i}"> ${p.label}`;
      listBox.appendChild(lbl);
    });
    // チェックが入ったら削除ボタン有効化
    listBox.querySelectorAll("input[type=checkbox]").forEach(cb => {
      cb.addEventListener("change", () => {
        const checked = listBox.querySelectorAll("input:checked").length > 0;
        deleteBtn.disabled = !checked;
      });
    });
  }
  $("delete-modal").style.display = "flex";
});

$("delete-confirm").addEventListener("click", () => {
  const checked = [...$("delete-list").querySelectorAll("input:checked")];
  if (checked.length === 0) {
    alert("削除するレシピを選んでください。");
    return;
  }
  $("delete-modal").style.display = "none";
  $("confirm-modal").style.display = "flex";
});

$("confirm-yes").addEventListener("click", () => {
  const arrRaw = JSON.parse(localStorage.getItem(LS_KEY) || "[]");
  const arr = arrRaw.map(item => typeof item === 'string' ? { label: item } : item );
  const checked = [...$("delete-list").querySelectorAll("input:checked")].map(el => Number(el.value));
  const newArr = arr.filter((_, i) => !checked.includes(i));

  localStorage.setItem(LS_KEY, JSON.stringify(newArr));
  renderPresets(newArr);

  $("confirm-modal").style.display = "none";
  showToast("削除しました!");
});

解説
削除ボタンを押した後も、いきなり削除せずモーダルで確認し誤操作防止。
まとめて削除に対応。
削除ボタンはチェックが1つもない時は無効化。
削除後は、renderPresets() でUIの更新と、トーストで削除完了を通知。

今後の改善案

社内のポートフォリオチャンネルに投稿したところ以下のFBをもらえたので、随時修正していきたいです!

  • 画面幅が中途半端な時に、ワット数の入力欄がずれている
  • スマホ版のレイアウトは「あたためる」ボタンがすぐ押せる位置にあるといいかも
  • ページ下部で斜め線がズレている

自分で気づけなかった部分もあるので、こうしてすぐにFBをいただけるのはありがたいですね!

まとめ

日ごろのちょっとした不便を、こうして自分で解決できるのはプログラミングの面白さの1つだなと改めて感じました!

自分用に作った小さなツールでも、形にしてみると意外と使いやすく日常のストレスがぐっと減りそうです。

こうした身近な課題をきっかけに、また別のツールを作ってみたいなと思います!

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?