見出し画像

印刷面付シュミレータ.html × Claude 3.5 Sonnet

update2024_10_11
早速あぷで。(下のhtmlのコードとURL先のhtmlも変更してあります)
・A判と菊判にそれぞれ4裁を追加しました。
菊半機で刷れるのが一応菊四までなのでそれより小さい四六判8切は
入れてありません。
・上クワエとドブを数値入力可能にしました。
前のままだとA全にA4が8面入りませんでした。
ドブの入れ方が関係してきますが、あくまでこれは小さい特寸サイズの端物
がどれくらい入るか目安を見る目的のため、複雑な事はあえて避けました。
・軽オフだとクワエは上ではなく左になるため、この場合も複雑にしたくなかったので。軽オフの場合はクワエ0にして使ってください。
http://printnet.droppages.net/imposition_simulator.html


for 印刷営業 & 生産管理 2024_10_10


Claude 3.5 Sonnetが熱い

ついこないだまでChatGPT4oとPerplexityがコーディングにはベストチョイスだと思ってたのに、今Claude 3.5 Sonnetにハマってます。はじめて課金しちゃおうかなと思い始めてます。

毎日使ってるんだけどすぐ文字数オーバーになっちゃう。
最近使ったのはvbaとhtml+CSS+javascriptで、部分的に修正箇所を示してくれるんだけど、もうずーーとやってると、めんどくさくなってきて、内容も理解せず、全コード出させてただコピペして動作確認。
良く見ると修正箇所は1行だけなのに全コード出させるもんだから、そりゃ、すぐMAXに達しちゃうわな(泣)

印刷面付シュミレータ.html

で、何かhtmlで作れそうなのないかなと考えてるうちに、そうだ面付シュミレータできるんかな?と急に思いついたってわけ。
簡単なプロンプトでかなり完成度高いコードを書いてくれたんでホント感動で、しかもClaude 3.5 Sonnetは右ペインでリアルタイムプレビューしてくれるからブラウザのウィンドウ1つで済むのが地味にGoodです。

プロンプト入れると右ペインでhtmlコードが流れ…
待ってるとプレビューが現れる。プレビューとコードは小さなタブで切り替えられるようになってました。こりゃ便利

プロンプト

1回目
html+javascriptで作りたい
1)用紙サイズ A全、A判半裁、菊全、菊半裁、四六全、四六半裁、四六4裁の7バリエーションの用紙サイズをプルダウンで選ぶと右側に罫線で表示
2)任意の製品仕上がりサイズを入力。但し縦向きと横向きをプルダウン等で選択可能とする
3)面付ボタンを押すと1)の用紙サイズの中に2)がいくつ並ぶか罫線を描画して表示
まとめると※1)用紙サイズを罫線で表示し、その中に納まるよう2)のサイズの罫線を面付し、敷き詰めて表示するウェブアプリを作りたい

2回目
1)上にクワエとして15mm、下にクワエ尻10mm取り、表示はクワエ15mm、クワエ尻10mm
2)製品サイズの天地左右すべてにドブ3mm加えてプレビューしてください。
3回目とつづく...

驚いたのは1回目のプロンプトだけで、求めていたレイアウトがもうほぼ完成してたし、用紙サイズも勝手に調べてくれちゃってるし。
これは完成度高いです。すばらい

で、Claudeが文字数オーバーになると続きを他のPerplexityとかでやろうとするんだけど、壊されちゃうんだよね。まぁたまたまかも知れないけど。
という訳で、現在の為替レートで円換算2980円くらい。悩むなホント、もっといいのが出てくるかも知れんし。
普段は毎日ばりばり使う訳じゃないし。。悩ましいです。

下記が文字オーバーする前の最終版 自前サーバに上げました。http://printnet.droppages.net/imposition_simulator.html
dropbox内にpublicフォルダを作ってホスティングしてくれるサービス。
月1000円。これも契約しちゃいました。以前は自宅サーバ立ててたんですけど、今の自宅賃貸は固定ipできない契約なんで。

htmlはこちら 

※社内公開するので、今後もう少し手を加えると思います。
update2024_10_11

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>印刷面付シミュレーター</title>
    <style>
        .container {
            display: flex;
            gap: 20px;
            padding: 20px;
        }
        .controls {
            width: 300px;
        }
        .preview {
            flex-grow: 1;
        }
        .canvas-container {
            border: 1px solid #ccc;
            margin-top: 10px;
            overflow: auto;
            position: relative;
        }
        select, input, button {
            width: 100%;
            margin-bottom: 10px;
            padding: 5px;
            box-sizing: border-box;
        }
        .input-group {
            display: flex;
            gap: 10px;
        }
        .input-group input {
            width: calc(50% - 5px);
        }
        button {
            padding: 10px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="controls">
            <h2>設定</h2>
            <label for="paperSize">用紙サイズ:</label>
            <select id="paperSize" onchange="calculateImposition()">
                <option value="a_full">A全判 (625×880mm)</option>
                <option value="a_half">A半裁 (625×440mm)</option>
                <option value="a_quarter">A判4裁 (438×310mm)</option>
                <option value="kiku_full">菊全判 (636×939mm)</option>
                <option value="kiku_half">菊半裁 (469×636mm)</option>
                <option value="kiku_quarter">菊判4裁 (467×316mm)</option>
                <option value="shiroku_full">四六全判 (788×1091mm)</option>
                <option value="shiroku_half">四六半裁 (788×545mm)</option>
                <option value="shiroku_quarter">四六4裁 (394×545mm)</option>
                <option value="shiroku_third">四六全三つ切り (364×788mm)</option>
            </select>

            <label for="productWidth">製品サイズ (mm):</label>
            <div class="input-group">
                <input type="number" id="productWidth" placeholder="幅" min="1" value="210">
                <input type="number" id="productHeight" placeholder="高さ" min="1" value="297">
            </div>

            <label for="orientation">製品方向:</label>
            <select id="orientation">
                <option value="portrait">縦向き</option>
                <option value="landscape">横向き</option>
            </select>

            <label for="kuwae">上クワエ (mm):</label>
            <input type="number" id="kuwae" min="0" value="15">

            <label for="bleed">断裁余白(ドブ) (mm):</label>
            <input type="number" id="bleed" min="0" value="3">

            <button id="calculateButton" onclick="calculateImposition()">面付計算</button>
        </div>

        <div class="preview">
            <h2>プレビュー</h2>
            <div class="canvas-container">
                <canvas id="previewCanvas"></canvas>
            </div>
        </div>
    </div>

    <script>
        const paperSizes = {
            a_full: { width: 880, height: 625 },
            a_half: { width: 440, height: 625 },
            a_quarter: { width: 438, height: 310 },
            kiku_full: { width: 939, height: 636 },
            kiku_half: { width: 636, height: 469 },
            kiku_quarter: { width: 467, height: 316 },
            shiroku_full: { width: 1091, height: 788 },
            shiroku_half: { width: 545, height: 788 },
            shiroku_quarter: { width: 545, height: 394 },
            shiroku_third: { width: 788, height: 364 }
        };

        const canvas = document.getElementById('previewCanvas');
        const ctx = canvas.getContext('2d');
        const SCALE = 0.5;
        const MARGIN = 20;

        function calculateImposition() {
            const paperSizeSelect = document.getElementById('paperSize');
            const productWidth = Number(document.getElementById('productWidth').value);
            const productHeight = Number(document.getElementById('productHeight').value);
            const orientation = document.getElementById('orientation').value;
            const kuwae = Number(document.getElementById('kuwae').value);
            const bleed = Number(document.getElementById('bleed').value);

            if (!productWidth || !productHeight) {
                alert('製品サイズを入力してください');
                return;
            }

            const paper = paperSizes[paperSizeSelect.value];
            canvas.width = paper.width * SCALE + (MARGIN * 2);
            canvas.height = paper.height * SCALE + (MARGIN * 2);

            ctx.clearRect(0, 0, canvas.width, canvas.height);

            ctx.strokeStyle = '#000';
            ctx.lineWidth = 2;
            ctx.strokeRect(MARGIN, MARGIN, paper.width * SCALE, paper.height * SCALE);

            // 用紙サイズを表示
            ctx.fillStyle = 'red';
            ctx.font = '12px Arial';
            ctx.fillText(`${paper.width}×${paper.height}mm`, MARGIN + 5, MARGIN + 15);

            ctx.strokeStyle = '#888';
            ctx.lineWidth = 1;
            ctx.setLineDash([5, 5]);
            
            const topMarginLine = MARGIN + (kuwae * SCALE);
            ctx.beginPath();
            ctx.moveTo(MARGIN, topMarginLine);
            ctx.lineTo(MARGIN + paper.width * SCALE, topMarginLine);
            ctx.stroke();

            ctx.setLineDash([]);

            let finalProductWidth = orientation === 'portrait' ? productWidth : productHeight;
            let finalProductHeight = orientation === 'portrait' ? productHeight : productWidth;

            finalProductWidth += (bleed * 2);
            finalProductHeight += (bleed * 2);

            const usableHeight = paper.height - kuwae;
            
            const cols = Math.floor(paper.width / finalProductWidth);
            const rows = Math.floor(usableHeight / finalProductHeight);

            const totalWidth = cols * finalProductWidth;
            const totalHeight = rows * finalProductHeight;
            const xOffset = (paper.width - totalWidth) / 2;
            const yOffset = (usableHeight - totalHeight) / 2;

            ctx.strokeStyle = '#0066ff';
            ctx.lineWidth = 1;

            for (let row = 0; row < rows; row++) {
                for (let col = 0; col < cols; col++) {
                    const x = (col * finalProductWidth * SCALE) + MARGIN + (xOffset * SCALE);
                    const y = (row * finalProductHeight * SCALE) + MARGIN + (kuwae * SCALE) + (yOffset * SCALE);
                    
                    ctx.setLineDash([5, 5]);
                    ctx.strokeStyle = '#0066ff';
                    ctx.strokeRect(x, y, finalProductWidth * SCALE, finalProductHeight * SCALE);
                    
                    ctx.setLineDash([]);
                    ctx.strokeStyle = '#000';
                    ctx.strokeRect(
                        x + (bleed * SCALE),
                        y + (bleed * SCALE),
                        (finalProductWidth - (bleed * 2)) * SCALE,
                        (finalProductHeight - (bleed * 2)) * SCALE
                    );
                }
            }

            const total = rows * cols;
            ctx.fillStyle = '#000';
            ctx.font = '14px Arial';
            ctx.fillText(`面付数: ${total}面`, MARGIN, canvas.height - 5);
        }

        document.getElementById('productWidth').addEventListener('keydown', function(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                document.getElementById('productHeight').focus();
            }
        });

        document.getElementById('productHeight').addEventListener('keydown', function(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                document.getElementById('orientation').focus();
            }
        });

        document.getElementById('orientation').addEventListener('keydown', function(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                document.getElementById('kuwae').focus();
            }
        });

        document.getElementById('kuwae').addEventListener('keydown', function(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                document.getElementById('bleed').focus();
            }
        });

        document.getElementById('bleed').addEventListener('keydown', function(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                document.getElementById('calculateButton').focus();
            }
        });

        // 初期表示
        calculateImposition();
    </script>
</body>
</html>


この記事が気に入ったらサポートをしてみませんか?