⚙️

ChatGPT-4oでモック画像からコードを書かせてみた話

2024/05/16に公開

ChatGPT-4oが話題だったので、挑戦してみました。

できたもの

筆者のひとり言は、じゃまにならないよう、引用ブロックで書きます。

入力1

  • ポンチ絵
  • こんな感じの処理を実現するHTML、JavaScript、CSSが欲しいな。

出力1

このようなツールチップを表示する機能を実現するためのHTML、CSS、JavaScriptの例を以下に示します。このコードは、英単語にカーソルを置くと、日本語の翻訳を表示するツールチップを実装します。

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tooltip Example</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="sentence">
        <span class="tooltip" data-translation="ペン・万年筆">pen</span>.
    </div>

    <script src="script.js"></script>
</body>
</html>

CSS (styles.css)

styles.css
body {
    font-family: Arial, sans-serif;
    padding: 20px;
}

.sentence {
    font-size: 24px;
}

.tooltip {
    position: relative;
    cursor: pointer;
    color: blue;
}

.tooltip::after {
    content: attr(data-translation);
    position: absolute;
    left: 50%;
    bottom: 150%;
    transform: translateX(-50%);
    background-color: #333;
    color: #fff;
    padding: 5px 10px;
    border-radius: 5px;
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.3s;
    pointer-events: none;
    z-index: 10;
}

.tooltip:hover::after {
    opacity: 1;
}

tooltip(ツールチップ)という言葉は入力画像にしか含まれていないため、画像から意味を認識してコーディングしていることが分かります。気持ち悪い(誉め言葉)です。

JavaScript (script.js)

今回は特にJavaScriptを使わなくてもCSSだけで実装可能です。ただし、JavaScriptで動的に翻訳データを追加したり、ツールチップの表示位置を調整する場合には以下のようなコードが考えられます。

script.js
document.addEventListener('DOMContentLoaded', function() {
    const tooltips = document.querySelectorAll('.tooltip');

    tooltips.forEach(tooltip => {
        tooltip.addEventListener('mouseenter', function() {
            const translation = tooltip.getAttribute('data-translation');
            const tooltipBox = document.createElement('div');
            tooltipBox.classList.add('tooltip-box');
            tooltipBox.textContent = translation;
            document.body.appendChild(tooltipBox);

            const rect = tooltip.getBoundingClientRect();
            tooltipBox.style.left = `${rect.left + rect.width / 2}px`;
            tooltipBox.style.top = `${rect.top - rect.height}px`;

            tooltip.addEventListener('mouseleave', function() {
                document.body.removeChild(tooltipBox);
            }, { once: true });
        });
    });
});

このコードを使うことで、指定された単語にカーソルを置くと、日本語の翻訳がツールチップとして表示されます。CSSでツールチップのスタイルをカスタマイズし、JavaScriptで動的な動きを追加することができます。

これでも良かったんですが、データファイルを別に切り出して、動的に扱えた方が良いよねということで追加入力を与えてみます。

入力2

データファイルは別に用意したいんだけど

出力2

データファイルを別に用意して、単語の翻訳情報をJSONファイルとして管理し、それをJavaScriptで読み込んで動的にツールチップを生成する方法を紹介します。

JSONファイル (translations.json)

まず、翻訳データをJSONファイルとして用意します。

translations.json
{
    "pen": "ペン・万年筆",
    "book": "本",
    "apple": "りんご"
}

HTML

次に、基本的なHTMLを設定します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tooltip Example</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="sentence">
        <span class="tooltip" data-word="pen">pen</span>,
        <span class="tooltip" data-word="book">book</span>,
        <span class="tooltip" data-word="apple">apple</span>.
    </div>

    <script src="script.js"></script>
</body>
</html>

CSS (styles.css)

CSS (styles.css)
body {
    font-family: Arial, sans-serif;
    padding: 20px;
}

.sentence {
    font-size: 24px;
}

.tooltip {
    position: relative;
    cursor: pointer;
    color: blue;
}

.tooltip-box {
    position: absolute;
    background-color: #333;
    color: #fff;
    padding: 5px 10px;
    border-radius: 5px;
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.3s;
    pointer-events: none;
    z-index: 10;
    transform: translateX(-50%);
}

.tooltip:hover .tooltip-box {
    opacity: 1;
}

JavaScript (script.js)

script.js
document.addEventListener('DOMContentLoaded', function() {
    fetch('translations.json')
        .then(response => response.json())
        .then(translations => {
            const tooltips = document.querySelectorAll('.tooltip');

            tooltips.forEach(tooltip => {
                const word = tooltip.getAttribute('data-word');
                const translation = translations[word];

                if (translation) {
                    const tooltipBox = document.createElement('div');
                    tooltipBox.classList.add('tooltip-box');
                    tooltipBox.textContent = translation;
                    tooltip.appendChild(tooltipBox);

                    tooltip.addEventListener('mouseenter', function() {
                        tooltipBox.style.left = `${tooltip.offsetWidth / 2}px`;
                        tooltipBox.style.top = `-${tooltipBox.offsetHeight + 10}px`;
                    });

                    tooltip.addEventListener('mouseleave', function() {
                        tooltipBox.style.opacity = '0';
                    });
                }
            });
        })
        .catch(error => console.error('Error loading translations:', error));
});

この方法では、JSONファイルから翻訳データを読み込み、該当する単語に対してツールチップを動的に生成します。これにより、翻訳データを容易に管理・更新できるようになります。

念のため、JSONファイルの想定フォーマットを尋ねてみます。

入力3

JSONファイルの書式を見せてよ

出力3

もちろんです。以下が、翻訳データを含むJSONファイルの具体例です。

JSONファイル (translations.json)

translations.json
{
    "pen": "ペン・万年筆",
    "book": "本",
    "apple": "りんご",
    "computer": "コンピュータ",
    "phone": "電話"
}

このファイルには、各英単語とその日本語訳がキーと値のペアとして保存されています。JSONファイルを translations.json という名前で保存し、上記のHTML、CSS、JavaScriptコードと一緒に同じディレクトリに置いてください。

いい感じですね。
ただ、ちょっと振り返って、出力2のHTMLを見直すと、
<span class="tooltip" data-word="pen">pen</span>,
data-word 属性をいちいち書くのが面倒そうだと思いました。

入力3

HTMLファイルにdata-wordをいちいち書くのが面倒です。

出力3

確かに、HTMLファイルにdata-word属性を手動で追加するのは手間がかかることがあります。これを改善するために、JavaScriptを用いて、テキストの中の単語に自動的にdata-word属性を付与し、ツールチップを生成する方法を示します。

JSONファイル (translations.json)

translations.json
{
    "pen": "ペン・万年筆",
    "book": "本",
    "apple": "りんご",
    "computer": "コンピュータ",
    "phone": "電話"
}

HTML

基本的なHTMLは以下のようになります。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tooltip Example</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="content">
        This is a pen, a book, and an apple. You can use a computer or a phone to read more.
    </div>

    <script src="script.js"></script>
</body>
</html>

CSS (styles.css)

CSSファイルは同じ内容を使います。

styles.css
body {
    font-family: Arial, sans-serif;
    padding: 20px;
}

#content {
    font-size: 24px;
}

.tooltip {
    position: relative;
    cursor: pointer;
    color: blue;
}

.tooltip-box {
    position: absolute;
    background-color: #333;
    color: #fff;
    padding: 5px 10px;
    border-radius: 5px;
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.3s;
    pointer-events: none;
    z-index: 10;
    transform: translateX(-50%);
}

.tooltip:hover .tooltip-box {
    opacity: 1;
}

JavaScript (script.js)

JavaScriptで、コンテンツ中の単語を自動的に検出し、ツールチップを追加する処理を行います。

script.js
document.addEventListener('DOMContentLoaded', function() {
    fetch('translations.json')
        .then(response => response.json())
        .then(translations => {
            const content = document.getElementById('content');
            const words = content.textContent.split(' ');
            content.innerHTML = ''; // Clear the content to rebuild it with tooltips

            words.forEach(word => {
                const cleanedWord = word.replace(/[.,!?]/g, ''); // Remove punctuation for matching
                if (translations[cleanedWord]) {
                    const span = document.createElement('span');
                    span.classList.add('tooltip');
                    span.textContent = word;
                    const tooltipBox = document.createElement('div');
                    tooltipBox.classList.add('tooltip-box');
                    tooltipBox.textContent = translations[cleanedWord];
                    span.appendChild(tooltipBox);
                    content.appendChild(span);
                    content.appendChild(document.createTextNode(' '));
                } else {
                    content.appendChild(document.createTextNode(word + ' '));
                }
            });
        })
        .catch(error => console.error('Error loading translations:', error));
});

説明

  1. HTML: テキスト全体を <div id="content"> に含めます。
  2. CSS: CSSは変更ありません。
  3. JavaScript:
  • JSONファイルから翻訳データを読み込みます。
  • テキストを単語ごとに分割し、各単語をチェックして翻訳が存在する場合は、 <span> 要素を作成し、ツールチップを追加します。
  • 各単語の最後にスペースを追加して元のテキスト構造を保持します。

これにより、HTMLファイルに手動で data-word 属性を追加する手間を省き、コンテンツの単語に自動的にツールチップを追加することができます。

たいていのことを書けてしまうので、おもしろくありません。ちょっと無理目なお願いをしたくなりました。

入力4

翻訳対象テキストをフォームで登録して、ローカルで実行できるようにできないかな?

出力4

フォームで翻訳対象のテキストを登録し、それに基づいてツールチップを表示する機能を追加したローカル実行可能なサンプルを作成します。これにより、ユーザーは自由にテキストを入力し、その中の単語に対してツールチップを生成できます。

JSONファイル (translations.json)

translations.json
{
    "pen": "ペン・万年筆",
    "book": "本",
    "apple": "りんご",
    "computer": "コンピュータ",
    "phone": "電話"
}

HTML

フォームでテキストを入力し、翻訳対象の単語にツールチップを表示するHTMLファイルです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tooltip Example</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <h1>Tooltip Example</h1>
    <form id="textForm">
        <label for="textInput">Enter your text:</label>
        <textarea id="textInput" rows="4" cols="50"></textarea>
        <button type="submit">Submit</button>
    </form>
    <div id="content"></div>

    <script src="script.js"></script>
</body>
</html>

CSS (styles.css)

styles.css
body {
    font-family: Arial, sans-serif;
    padding: 20px;
}

h1 {
    font-size: 24px;
}

form {
    margin-bottom: 20px;
}

#content {
    font-size: 24px;
}

.tooltip {
    position: relative;
    cursor: pointer;
    color: blue;
}

.tooltip-box {
    position: absolute;
    background-color: #333;
    color: #fff;
    padding: 5px 10px;
    border-radius: 5px;
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.3s;
    pointer-events: none;
    z-index: 10;
    transform: translateX(-50%);
}

.tooltip:hover .tooltip-box {
    opacity: 1;
}

JavaScript (script.js)

script.js
document.addEventListener('DOMContentLoaded', function() {
    fetch('translations.json')
        .then(response => response.json())
        .then(translations => {
            const form = document.getElementById('textForm');
            const content = document.getElementById('content');

            form.addEventListener('submit', function(event) {
                event.preventDefault();
                const textInput = document.getElementById('textInput').value;
                const words = textInput.split(' ');
                content.innerHTML = ''; // Clear the content to rebuild it with tooltips

                words.forEach(word => {
                    const cleanedWord = word.replace(/[.,!?]/g, ''); // Remove punctuation for matching
                    if (translations[cleanedWord]) {
                        const span = document.createElement('span');
                        span.classList.add('tooltip');
                        span.textContent = word;
                        const tooltipBox = document.createElement('div');
                        tooltipBox.classList.add('tooltip-box');
                        tooltipBox.textContent = translations[cleanedWord];
                        span.appendChild(tooltipBox);
                        content.appendChild(span);
                        content.appendChild(document.createTextNode(' '));
                    } else {
                        content.appendChild(document.createTextNode(word + ' '));
                    }
                });
            });
        })
        .catch(error => console.error('Error loading translations:', error));
});

説明

  1. HTML:
    フォーム ( <form> ) を追加し、ユーザーがテキストを入力できるようにします。
    入力されたテキストを表示するための <div id="content"> を用意します。
  2. CSS:
    ツールチップのスタイルを設定します。
  3. JavaScript:
    • ページが読み込まれた際に、JSONファイルから翻訳データを取得します。
    • フォームの送信イベント (submit イベント) をリスンし、入力されたテキストを処理します。
    • テキストを単語に分割し、各単語に対してツールチップを生成します。

これにより、ユーザーは任意のテキストをフォームに入力し、翻訳対象の単語にツールチップを表示することができます。この仕組みはローカル環境で動作するので、ファイルを同じディレクトリに配置し、ブラウザで index.html ファイルを開くだけで機能します。

Discussion