H5 雪碧图 移动的机器猫

时间:2022-12-26 16:52:57

精灵图(英语:Sprite),又被称为雪碧图或拼合图。在计算机图形学中,当一张二维图像 集成进场景中,成为整个显示图像的一部分时,这张图就称为精灵图。

本文中用的就是这张,来自爱给网。

H5 雪碧图 移动的机器猫

效果

H5 雪碧图 移动的机器猫

操作

键盘上下左右控制移动

document.addEventListener("keydown", (ev) => {
  let x = 0,
    y = 0;
  if (ev.code === "ArrowUp") y = -1;
  if (ev.code === "ArrowDown") y = 1;
  if (ev.code === "ArrowLeft") x = -1;
  if (ev.code === "ArrowRight") x = 1;
  if (x || y) move(x, y);
});

动画

通过判断不同状态来展示不同动画

function sprite() {
  /** @type {{x:number,y:number}[]} */
  let anim = anims[currSprite];
  let animIndex = 0;
  let render = () => {
    let curr = anim[animIndex];
    let currX = Math.round(curr.x * 25); // 25 指单个小图的宽度
    let currY = Math.round(curr.y * 38); // 38 指单个小图的高度

    backgroundPosition = `background-position: ${currX}px ${currY}px;`;
    doraemon.setAttribute("style", `${transform}${backgroundPosition}`);
    animIndex++;
    if (anim.length === animIndex) animIndex = 0;
  };
  render();
  return setInterval(render, 200); // 200 是指每帧渲染间隔0.2s
}

源码

没有进行精简,属于粗略的代码

<!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" />
    <style>
      .doraemon {
        width: 25px;
        height: 38px;
        position: relative;
        background-image: url("./assets/doraemon.png");
      }

      .doraemon .name {
        position: absolute;
        top: -14px;
        left: 50%;
        transform: translateX(-50%);
        font-size: 12px;
        text-align: center;
        white-space: nowrap;
      }
    </style>
  </head>

  <body>
    <div class="doraemon">
      <div class="name">哆啦A梦</div>
    </div>

    <script>
      // 写一下 doraemon 移动

      // 操作元素
      let doraemon = document.querySelector(".doraemon");
      // 当前位置
      let pos = { x: 0, y: 0 };
      // 移动速度
      let speed = 2;
      // 当前动画
      let currSprite = "idle";

      // 默认
      let idleSprite = [{ x: 2, y: 0 }];
      // 向下
      let downSprite = [
        { x: 1, y: 0 },
        { x: 2, y: 0 },
        { x: 3, y: 0 },
      ];
      // 向上
      let upSprite = [
        { x: 1, y: 1 },
        { x: 2, y: 1 },
        { x: 3, y: 1 },
      ];
      // 向左
      let leftSprite = [
        { x: 1, y: 3 },
        { x: 2, y: 3 },
        { x: 3, y: 3 },
      ];
      // 向右
      let rightSprite = [
        { x: 1, y: 2 },
        { x: 2, y: 2 },
        { x: 3, y: 2 },
      ];
      // 动画集
      let anims = {
        idle: idleSprite,
        down: downSprite,
        up: upSprite,
        left: leftSprite,
        right: rightSprite,
      };
      // 当前操作的位置
      let backgroundPosition = "";
      // 当前的位移
      let transform = "";
      // 初始动画
      let spriteInterval = sprite();
      // 延迟默认
      let idleTimeout = 0;

      document.addEventListener("keydown", (ev) => {
        let x = 0,
          y = 0;
        if (ev.code === "ArrowUp") y = -1;
        if (ev.code === "ArrowDown") y = 1;
        if (ev.code === "ArrowLeft") x = -1;
        if (ev.code === "ArrowRight") x = 1;
        if (x || y) move(x, y);
      });

      function sprite() {
        /** @type {{x:number,y:number}[]} */
        let anim = anims[currSprite];
        let animIndex = 0;
        let render = () => {
          let curr = anim[animIndex];
          let currX = Math.round(curr.x * 25);
          let currY = Math.round(curr.y * 38);

          backgroundPosition = `background-position: ${currX}px ${currY}px;`;
          doraemon.setAttribute("style", `${transform}${backgroundPosition}`);
          animIndex++;
          if (anim.length === animIndex) animIndex = 0;
        };
        render();
        return setInterval(render, 200);
      }

      /**
       * 元素移动
       * @param {number} x
       * @param {number} y
       */
      function move(x, y) {
        clearTimeout(idleTimeout);

        idleTimeout = setTimeout(() => {
          clearInterval(spriteInterval);
          currSprite = "idle";
          spriteInterval = sprite();
        }, 500);

        x *= speed;
        y *= speed;

        pos.x += x;
        pos.y += y;

        if (x > 0 && currSprite != "right") {
          clearInterval(spriteInterval);
          currSprite = "right";
          spriteInterval = sprite();
        }
        if (y > 0 && currSprite != "down") {
          clearInterval(spriteInterval);
          currSprite = "down";
          spriteInterval = sprite();
        }
        if (x < 0 && currSprite != "left") {
          clearInterval(spriteInterval);
          currSprite = "left";
          spriteInterval = sprite();
        }
        if (y < 0 && currSprite != "up") {
          clearInterval(spriteInterval);
          currSprite = "up";
          spriteInterval = sprite();
        }
        transform = `transform: translate(${pos.x}px,${pos.y}px);`;

        doraemon.setAttribute("style", `${transform}${backgroundPosition}`);
      }
    </script>
  </body>
</html>

地址

https://github.com/linyisonger/H5.Examples