フロントエンド - ネイティブ HTML cat cat max table pet (ソースコード付き)

I.はじめに

マックスのボスとコボルトのボスが作ったテーブルペットを見たので、ウェブで簡単に実現したようなものです

2. コードパッケージ 

https://wwwf.lanzout.com/iWfER0ze0cqd
パスワード: fg88

 3. 簡単な効果

ランダムアクションの簡単な使用(重みを設定可能)


第四に、ピットを踏む状況

メイン ループのループ内にない場合は、ここでは使用できません。これにより、複数のループ サイクルが開かれることになります。

animationId = requestAnimationFrame(loop);  // 浏览器提供的 API,用于优化动画性能并在重绘之前在主线程上执行指定的函数

 タイマーを関数に設定する場合は、グローバル変数にマウントするのが最善です。後で破棄するのに便利です!

1. 変数の初期化

2. タイマーを作成します (関数内) 

3. タイマーをクリアする

 ico アイコンと cur アイコンの両方を Web で適用できます。

注: サイズは 32x32 ピクセルを超えることはできません。

クリック リスナーは親ボックスに設定されています。子ボックスをクリックしてもリスナーはトリガーされません。

解決策: 子ボックスをクリックできないように設定してください。

.cywl img {
    width: 90px;
    height: 90px;
    /* 无法选中 */
    pointer-events: none;
    user-select: none;
}

5、メインページのコード

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <link rel="stylesheet" href="./index.css">
    <style>
        .cywl {
            position: fixed;
            width: 100px;
            height: 100px;
            z-index: 9999;
            left: 50px;
            bottom: 50px;
            cursor: url(./Maxwell_Who-CatCursor/alternate.ico),
                default;
            display: flex;

            /* background-color: #5ee7df; */
        }

        .cywl img {
            width: 90px;
            height: 90px;
            /* 无法选中 */
            pointer-events: none;
            user-select: none;
        }
    </style>
</head>

<body style="height: 5000px; background-image: linear-gradient(200deg, #5ee7df, #b490ca);">
    <!--宠物开始-->
    <div id="pet" class="cywl">
        <img id="pet-img" src="./max/stand1.png">
    </div>
    <!--宠物结束-->

    <script>
        // 创建 pet 对象
        const pet = {
            x: 50,   // 宠物初始位置的横坐标 (左下角开始)
            y: 50,
            vx: 1,   // 水平方向上宠物前进的速度
            vy: 0   // // 垂直方向上宠物前进的速度
        };

        // -------------------------------------------------------------动作
        // 动作权重
        // 权重问题:将所有权重相加,(得到一个大范围,那么就让随机数落到这个范围内,而对应的权重,就是落到的对应位置中)
        var actions = {
            // 普通
            walkleft: 1,
            walkright: 1,

            fish: 1,
            sleep: 1,
            kiss: 1,

            stand: 1,


        };

        // 存储宠物行走动画帧的数组
        const LeftwalkFrames = []; // 左走
        const RightwalkFrames = []; // 右走

        const DragFrames = [];  // 拖拽

        const fishFrames = [];
        const kissFrames = [];
        const sleepFrames = [];

        const standFrames = [];

        const fallingFrames = [];


        // 初始化 定时器
        var ttt = null;
        var dragTime = null;

        var action = 'stand';


        //1、将对象中的动作按照权重转换为数组。可以使用 Object.keys 方法获取对象的键,
        //2、再使用 Array.map 方法将每个键转换为对象 {name: key, weight: actions[key]}。
        //3、最后使用 Array.reduce 方法将多个对象合成一个数组
        var actionList = Object.keys(actions).map(function (key) {
            return {
                name: key,
                weight: actions[key]
            };
        }).reduce(function (prev, curr) {
            return prev.concat(curr);
        }, []);


        // 根据权重随机选择动作 
        // 权重问题:将所有权重相加,(得到一个大范围,那么就让随机数落到这个范围内,而对应的权重,就是落到的对应位置中)

        function randomAction() {
            var totalWeight = actionList.reduce(function (prev, curr) {
                return prev + curr.weight;
            }, 0);
            // console.log(totalWeight);

            var randomNum = Math.random() * totalWeight;

            for (var i = 0; i < actionList.length; i++) {
                if (randomNum <= actionList[i].weight) {
                    return actionList[i].name;
                }
                randomNum -= actionList[i].weight;
            }
        }
        // -------------------------------------------------------------动作




        const img111 = new Image();
        img111.src = `./max/falling1.png`;
        fallingFrames.push(img111);

        // 创建动画序列  
        for (let i = 1; i < 13; i++) {
            // 将行走动画帧添加到 walkFrames 数组中

            const img = new Image();
            img.src = `./max/walkright${i}.png`;
            RightwalkFrames.push(img);

            const img2 = new Image();
            img2.src = `./max/walkleft${i}.png`;
            LeftwalkFrames.push(img2);

            // 其他

            const img3 = new Image();
            img3.src = `./max/drag${i}.png`;
            DragFrames.push(img3);

            const img4 = new Image();
            img4.src = `./max/fish${i}.png`;
            fishFrames.push(img4);

            const img5 = new Image();
            img5.src = `./max/kiss${i}.png`;
            kissFrames.push(img5);

            const img6 = new Image();
            img6.src = `./max/sleep${i}.png`;
            sleepFrames.push(img6);

            const img7 = new Image();
            img7.src = `./max/stand${i}.png`;
            standFrames.push(img7);

        }

        // 绘制宠物
        function drawPet(anyFrames = RightwalkFrames) {
            const frameIndex = Math.floor(Date.now() / 100) % anyFrames.length;  // 计算当前应该绘制的动画帧的索引
            const img = anyFrames[frameIndex]; // 获取当前应该绘制的动画帧

            document.querySelector('.cywl img').src = img.src;  // 更新宠物的显示图像
        }



        // 更新宠物位置
        function updatePet() {


            pet.x += pet.vx;   // 更新宠物在水平方向的位置
            // pet.y += pet.vy;

            // 超出屏幕左边
            if (pet.x < 0) {
                action = 'walkright'
            }
            // 超出屏幕右边
            if (pet.x + petDiv.clientWidth > window.innerWidth) {
                action = 'walkleft'
            }



            petDiv.style.left = pet.x + 'px';   // 更新宠物所在 div 元素的横坐标位置
            petDiv.style.bottom = pet.y + 'px';
        }



        // ----------------------------------------------------------------------处理用户交互

        // 定位
        const petDiv = document.querySelector('#pet');
        petDiv.style.left = pet.x + 'px';   // 更新宠物所在 div 元素的横坐标位置
        petDiv.style.bottom = pet.y + 'px';

        // 禁用图片点击
        const petImg = document.querySelector('#pet-img');
        petImg.style.pointerEvents = 'none';


        var isDragging = false;   // 标记是否正在拖拽中
        var diffX = 0;    // 鼠标指针与盒子左上角的偏移量
        var diffY = 0;


        let animationId = null;


        // 鼠标按下
        petDiv.addEventListener('mousedown', function (event) {

            action = '';

            clearInterval(petTimer); // 暂停宠物行动的定时器

            // 判断鼠标是否在 div 元素内按下,并记录下偏移量
            if (event.target === petDiv) {
                isDragging = true;
                diffX = event.clientX - petDiv.offsetLeft;
                diffY = event.clientY - petDiv.offsetTop;

                // 拖拽定时器
                dragTime = setInterval(function drag() {
                    // 显示拖拽 图片
                    drawPet(DragFrames);

                    // 这里不能用这个,会导致开启多个loop
                    // animationId = requestAnimationFrame(loop);  // 浏览器提供的 API,用于优化动画性能并在重绘之前在主线程上执行指定的函数

                }, 100);

            }
        });



        // 鼠标拖动
        document.addEventListener('mousemove', function (event) {
            // 如果正在拖拽中,则更新盒子位置
            if (isDragging === true) {



                pet.x = event.clientX - diffX
                pet.y = event.clientY - diffY

                petDiv.style.left = pet.x + 'px';
                petDiv.style.top = pet.y + 'px';
            }

        });

        // 鼠标抬起
        document.addEventListener('mouseup', function (event) {
            if (isDragging === true) {

                // 清除旧的定时器
                clearInterval(ttt);
                clearInterval(dragTime);

                // 停止拖拽
                isDragging = false;

                action = 'stand';

                ttt = setInterval(function name() {
                    action = randomAction();
                }, 3000);


                // 超出屏幕 回到 指定位置 
                if (pet.y < 0 || pet.y + petDiv.clientHeight > window.innerHeight || pet.x + petDiv.clientWidth > window.innerWidth || pet.x < 0) {
                    pet.x = 500;
                    pet.y = 500;
                    const petDiv = document.querySelector('#pet');
                    petDiv.style.left = 500 + 'px';   // 更新宠物所在 div 元素的位置
                    petDiv.style.top = 500 + 'px';
                    // console.log(1111111)
                }


                // 显示下落 图片
                drawPet(fallingFrames);
                // animationId = requestAnimationFrame(loop);  // 浏览器提供的 API,用于优化动画性能并在重绘之前在主线程上执行指定的函数

                // loop();
            }

        });

        // 宠物行动的定时器,每 3 秒执行一次 doAction 函数
        var petTimer = setInterval(function name() {
            action = randomAction();
        }, 3000);




        // ----------------------------------------------------------------------
        // 主循环
        function loop() {


            console.log(action);
            if (action == 'walkleft') {
                // 执行 leftwalk 动作
                pet.vx = -0.5;
                updatePet();
                drawPet(LeftwalkFrames);

            }

            if (action == 'walkright') {
                pet.vx = 0.5;
                updatePet();
                drawPet(RightwalkFrames);

            }

            if (action == 'fish') {
                // updatePet();
                drawPet(fishFrames);

            }

            if (action == 'kiss') {
                // updatePet();
                drawPet(kissFrames);

            }

            if (action == 'sleep') {
                // updatePet();
                drawPet(sleepFrames);

            }

            if (action == 'stand') {
                // updatePet();
                drawPet(standFrames);

            }
            requestAnimationFrame(loop);  // 浏览器提供的 API,用于优化动画性能并在重绘之前在主线程上执行指定的函数
        }

        // 启动循环
        loop();
    </script>
</body>

</html>

おすすめ

転載: blog.csdn.net/Pan_peter/article/details/131264676