生成AI+スマホで作成「WordPress(ブログ)で使えるJavaScript」 横スクロール

コードエディター 本文

<canvas id="bikeCanvas" width="320" height="100"></canvas>

カスタムJavaScript

    const canvas = document.getElementById('bikeCanvas');
    const ctx = canvas.getContext('2d');

    let x = -60; // 自転車のX座標
    const speed = 2; // 自転車の速度
    let angle = 0; // タイヤとペダルの回転角度
    let wobble = 0; // 揺れの効果のためのカウンター

    // 雲のデータ(x, y, スピード)
    const clouds = [
        { x: 50,  y: 20, s: 0.5 },
        { x: 180, y: 35, s: 0.3 },
        { x: 300, y: 15, s: 0.4 }
    ];

    function drawCloud(cx, cy) {
        ctx.fillStyle = "white";
        ctx.beginPath();
        ctx.arc(cx, cy, 10, 0, Math.PI * 2);
        ctx.arc(cx + 10, cy - 5, 12, 0, Math.PI * 2);
        ctx.arc(cx + 20, cy, 10, 0, Math.PI * 2);
        ctx.fill();
    }

    function drawWheel(wx, wy, radius, rotation) {
        ctx.save();
        ctx.translate(wx, wy);
        ctx.rotate(rotation);
        
        ctx.beginPath();
        ctx.arc(0, 0, radius, 0, Math.PI * 2);
        ctx.stroke();

        for(let i = 0; i < 4; i++) {
            ctx.beginPath();
            ctx.moveTo(0, -radius);
            ctx.lineTo(0, radius);
            ctx.rotate(Math.PI / 4);
            ctx.stroke();
        }
        ctx.restore();
    }

    // ペダルを描画する関数
    function drawPedal(px, py, rotation) {
        const pedalRadius = 5;
        const crankLength = 10;

        ctx.save();
        ctx.translate(px, py); // ペダル軸へ移動
        ctx.rotate(rotation); // 回転

        // クランク
        ctx.beginPath();
        ctx.moveTo(0, 0);
        ctx.lineTo(crankLength, 0);
        ctx.lineWidth = 2;
        ctx.stroke();

        // ペダル本体
        ctx.beginPath();
        ctx.rect(crankLength - 3, -2, 6, 4); // 短い長方形でペダルを表現
        ctx.fill();
        ctx.stroke();
        ctx.restore();
    }

    // 棒人間を描画する関数
    function drawStickFigure(sx, sy) {
        ctx.strokeStyle = "#333";
        ctx.lineWidth = 2;

        // 頭
        ctx.beginPath();
        ctx.arc(sx + 20, sy - 35, 6, 0, Math.PI * 2);
        ctx.stroke();

        // 体
        ctx.beginPath();
        ctx.moveTo(sx + 20, sy - 29);
        ctx.lineTo(sx + 20, sy - 15);
        ctx.stroke();

        // 腕(ハンドルを握る形)
        ctx.beginPath();
        ctx.moveTo(sx + 20, sy - 28);
        ctx.lineTo(sx + 25, sy - 22); // 肩から肘
        ctx.lineTo(sx + 30, sy - 25); // 肘からハンドル
        ctx.stroke();

        // 足(ペダルを漕ぐ形)
        ctx.beginPath();
        ctx.moveTo(sx + 20, sy - 15);
        ctx.lineTo(sx + 15, sy - 5); // 股関節から膝
        ctx.lineTo(sx + 10, sy + 5); // 膝から足
        ctx.stroke();

        ctx.beginPath(); // もう一方の足
        ctx.moveTo(sx + 20, sy - 15);
        ctx.lineTo(sx + 25, sy - 5);
        ctx.lineTo(sx + 30, sy + 5);
        ctx.stroke();
    }

    function animate() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // --- 1. 雲の描画と更新 ---
        clouds.forEach(c => {
            drawCloud(c.x, c.y);
            c.x -= c.s;
            if (c.x < -40) c.x = 360;
        });

        // --- 2. 地面 ---
        ctx.strokeStyle = "#555";
        ctx.beginPath();
        ctx.moveTo(0, 85); ctx.lineTo(320, 85);
        ctx.stroke();

        // --- 3. 自転車の描画 ---
        ctx.strokeStyle = "#333";
        ctx.fillStyle = "#333"; // ペダルの塗りつぶし用
        ctx.lineWidth = 2;

        // ガタガタ効果
        const wobbleOffset = Math.sin(wobble) * 2; // -2から+2の範囲で上下に揺れる
        const bikeY = 80 + wobbleOffset;

        // タイヤ
        drawWheel(x, bikeY, 12, angle);       // 後輪
        drawWheel(x + 40, bikeY, 12, angle);  // 前輪

        // ペダル
        const pedalX = x + 20; // ペダルの中心X座標
        const pedalY = bikeY;  // ペダルの中心Y座標
        drawPedal(pedalX, pedalY, angle); // クランクとペダルを回転

        // フレーム
        ctx.beginPath();
        ctx.moveTo(x, bikeY);
        ctx.lineTo(x + 15, bikeY - 15);
        ctx.lineTo(x + 35, bikeY - 15);
        ctx.lineTo(x + 20, bikeY);
        ctx.lineTo(x, bikeY);
        ctx.moveTo(x + 15, bikeY - 15); ctx.lineTo(x + 10, bikeY - 22);
        ctx.moveTo(x + 5, bikeY - 22); ctx.lineTo(x + 15, bikeY - 22);
        ctx.moveTo(x + 35, bikeY - 15); ctx.lineTo(x + 40, bikeY);
        ctx.moveTo(x + 35, bikeY - 15); ctx.lineTo(x + 38, bikeY - 25);
        ctx.moveTo(x + 33, bikeY - 25); ctx.lineTo(x + 43, bikeY - 25);
        ctx.stroke();

        // 棒人間
        drawStickFigure(x, bikeY);

        // --- 4. 座標の更新 ---
        x += speed;
        angle += speed * 0.1; // 進む距離に合わせてタイヤとペダルを回転
        wobble += 0.1; // 揺れカウンターを増加

        if (x > canvas.width + 40) {
            x = -60;
        }

        requestAnimationFrame(animate);
    }

    animate();

カスタムCSS

        canvas { 
            background: #87CEEB; /* 空の色 */
            border: 2px solid #333;
            width: 320px;
            height: 100px;
        }