29
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【個人開発】最新Web技術をフル活用して「人間語→犬語翻訳アプリ」をガチ実装した話【Web Components / Web Worker / IndexedDB】

29
Posted at

突然ですが、皆さん疲れていませんか?
複雑な要件定義、終わらないデバッグ、迫りくる納期...

そんな現代社会に必要なのは、「知性」を捨てて「本能」に還ることだと思いました。

そこで、入力された言葉をすべて「ワン!」に変換するだけのアプリを、モダンなWeb標準技術をフル活用して作りました。

その名も「犬語変換アプリ」です。

この記事では、このアプリの裏側にある技術スタックを紹介します。

image.png

デモサイト

🐕 作ったもの

犬語変換アプリ
人間の言葉を入力すると、AI(という名のランダム関数)が感情豊かに「ワン!」に翻訳してくれます。

主な機能

  • 翻訳機能: どんな名文も「ワン!」になります。
  • 履歴機能: 過去の遠吠えをIndexedDBに保存します。
  • シェア機能: 翻訳結果をXやLINEで拡散できます。
  • PWA対応: インストールしてオフラインでも吠えられます。

技術スタック

フレームワーク全盛の時代ですが、今回はあえてVanilla JS (標準機能) の限界に挑みました。
「jQueryもReactもVueも使わない。信じられるのはブラウザ標準APIだけ」という縛りプレイです。

カテゴリ 技術 用途
Component Web Components 変換ボタンの完全なカプセル化
Thread Web Worker 翻訳処理(文字列置換)の非同期実行
Storage IndexedDB 翻訳履歴の永続化
Graphics Canvas API 背景の肉球パーティクル物理演算
App PWA オフライン動作・インストール対応

こだわりの実装ポイント

1. Web Worker で「重い翻訳処理」を非同期化

「テキストを『ワン』に置換するだけなら一瞬では?」
その通りです。

しかし、将来的に「100万文字の小説を一気に犬語にしたい」というニーズがあるかもしれません(ない)。
メインスレッドをブロックしてUIを固まらせないよう、翻訳ロジックは Web Worker に逃がしました。

// script.js (抜粋)
const workerCode = `
self.onmessage = function(e) {
    const { text, dogWords } = e.data;
    // ... 複雑な(ランダムな)翻訳アルゴリズム ...
    self.postMessage({ result: result.join(' ') });
};
`;
const blob = new Blob([workerCode], { type: "application/javascript" });
const worker = new Worker(URL.createObjectURL(blob));

Blob URLを使ってインラインでWorkerを生成する変態実装です。ファイル管理が楽になります。

2. Web Components (Shadow DOM) でボタンを隔離

変換ボタン <dog-button>Web Components で実装しました。
Shadow DOM を使うことで、外部のCSSの影響を完全に遮断しています。

class DogButton extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
    }
    // ...
}
customElements.define('dog-button', DogButton);

これで、どんなに汚いCSS環境に放り込まれても、このボタンだけは高潔な犬としての尊厳(スタイル)を保ち続けます。

3. IndexedDB で「遠吠え履歴」を管理

たかが履歴、されど履歴。
localStorage でも十分ですが、あえて非同期NoSQLデータベースである IndexedDB を採用しました。

class HistoryDB {
    constructor() {
        this.dbName = 'DogConverterDB';
        this.storeName = 'history';
    }
    // ... PromiseでラップしたCRUD処理 ...
}

「過去に自分が何を吠えたか」を数万件保存してもパフォーマンスが落ちません。誰が得するのかは不明です。

4. Canvas API による物理演算背景

背景でふわふわ浮いている肉球やパーティクル。
これはCSSアニメーションではなく、Canvas API で描画し、JavaScriptで物理演算しています。

さらに、「肉球をクリックすると破裂する」 という無駄なインタラクションも実装しました。
背景のCanvasは pointer-events: none でクリックを透過させていますが、JavaScript側で座標計算を行い、当たり判定を自前で実装しています。

// script.js (抜粋)
checkClick(x, y) {
    // 全パーティクルとの距離を計算して当たり判定
    for (let i = this.particles.length - 1; i >= 0; i--) {
        const p = this.particles[i];
        const dist = Math.sqrt((x - p.x)**2 + (y - p.y)**2);
        if (dist < p.size * 1.5) {
            this.explode(p.x, p.y, p.color); // 爆発エフェクト
            this.particles.splice(i, 1);
            return true;
        }
    }
}

無駄に requestAnimationFrame を回して、CPUリソースを消費して「癒やし」を提供します。

まとめ

「ネタアプリこそ、本気で作る」

これが今回のテーマでした。
普段の業務ではライブラリに頼りがちな部分を、あえて標準APIだけで実装してみると、ブラウザの進化や基礎技術の重要性に改めて気づかされます。

このアプリが、皆さんの殺伐としたタイムラインに一瞬の「ワン!」をもたらすことを願っています。

もし気に入ったらいいねストックフォローをお願いしますワン!

29
4
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
29
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?