H5 雪碧图 移动的机器猫

news2025/1/21 16:41:14

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

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

img

效果

img

操作

键盘上下左右控制移动

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/105697.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python:Flask简介与实践

文章目录简介一、简单使用二、调试模式三、路由四、路径变量五、构造URL六、HTTP方法七、静态文件八、模板生成九、日志输出十、处理请求1. Request 对象十一、文件上传十二、Cookies十三、重定向和错误十四、响应处理十五、Sessions十六、模板简介1. 模板标签2. 继承3. 控制流…

超高精度PID控制器的特殊功能(2)——远程操作软件及其安装使用

摘要&#xff1a;远程控制软件是高级PID调节器随机配备的一种计算机软件&#xff0c;可在计算机上远程进行调节器的所有操作&#xff0c;并还具有过程曲线显示和存储功能。本文主要针对VPC 2021系列超高精度PID控制器&#xff0c;介绍了随机配备的控制软件的安装和一些最基本的…

2022-12-21 Buildroot创建自己的软件包,把一个c应用编译到系统里面去运行

一、Buildroot 编译完成后&#xff0c;会在 /buildroot/output/xxxx/host/ 目录下&#xff0c;生成交叉编译工具&#xff0c;我们可以用来编译目标程序。 1、比如我现在要编译下面的c文件 #include <stdio.h> #include <stdlib.h> int main(int argc,char *argv[…

分布式是大数据处理的万能药?

前言&#xff1a;分布式是大数据处理的万能药&#xff1f;今天叶秋学长跟大家一起探讨这个问题~ 使用分布式集群来处理大数据是当前的主流&#xff0c;将一个大任务拆分成多个子任务分布到多个节点进行处理通常能获得显著的性能提升。因此&#xff0c;只要发现处理能力不足就可…

人数超员识别系统 yolov5

人数超员识别系统基于计算机视觉分析技术yolov5网络架构对现场画面实时分析&#xff0c;如监测到区域超员时&#xff0c;立刻抓拍存档并告警提示。YOLOv5是一种单阶段目标检测算法&#xff0c;该算法在YOLOv4的基础上添加了一些新的改进思路&#xff0c;使其速度与精度都得到了…

Java日志技术是什么

文章目录日志技术日志技术介绍日志技术体系日志技术 日志技术介绍 想清楚的知道一个系统运行的过程和详情就需要日志记录 日志介绍: 生活中的日志&#xff1a; 生活中的日志就好比日记&#xff0c;可以记录你生活的点点滴滴。 程序中的日志&#xff1a; 程序中的日志可以用来记…

04---springboot实现增删改查

1、配置文件 application.yml server:port: 8081 spring:mvc:path match:matching-strategy: ant_path_matcherdatasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: 123456url: jdbc:mysql://localhost:3306/management?useUnicodetrue&use…

C++ STL 之关联容器 map 详解

文章目录Part.I AttentionChap.I 注意事项Chap.II 操作技巧Part.II FuncitonPart.III CodeChap.I mapChap.II unordered_mapChap.III multimapPart.I Attention C 中 map 提供的是一种键值对容器&#xff0c;里面的数据都是成对出现的&#xff0c;每一对中的第一个值称之为关键…

博苑股份冲刺创业板上市:上半年净利润约1亿元,李成林为董事长

近日&#xff0c;山东博苑医药化学股份有限公司&#xff08;下称“博苑股份”或“博苑医药”&#xff09;在深圳证券交易所创业板更新招股书。据贝多财经了解&#xff0c;博苑股份于2022年6月17日递交招股书&#xff0c;准备在创业板上市。 本次冲刺创业板上市&#xff0c;博苑…

服务的消费方式和服务熔断

目录 1. 服务消费方式 1.1 RestTemplate 1.2 feign 2. 服务熔断&#xff08;降级&#xff09; 2.1 在微服务架构中服务熔断的必要性 健康的微服务集群&#xff1a; ​编辑 出现故障&#xff1a; ​编辑 系统雪崩&#xff1a; ​编辑 2.2 hystrix 2.3 hystrix的使用…

[Linux]多线程的同步和互斥(线程安全 | 互斥锁 | 死锁 | 条件变量)

文章目录Linux线程互斥进程线程间的互斥相关背景概念互斥量mutex互斥量的接口初始化互斥量销毁互斥量互斥量的加锁和解锁互斥量实现原理可重入vs线程安全常见线程不安全情况常见线程安全的情况常见不可重入的情况常见可重入的情况可重入与线程安全的联系可重入与线程安全的区别…

你易忽略的三极管电路问题1:下拉电阻

如下这个三极管共射极驱动电路中&#xff0c;B、E极之间的下拉电阻的作用&#xff1f;是否可以将其去除&#xff1f;该电阻有两个重要的作用&#xff1a;在驱动信号关闭时给三极管基极一个固定的电平。当驱动信号&#xff08;SIGNAL&#xff09;关闭时&#xff0c;若没有下拉电…

搭建Python环境(~保姆级别服务~)

文章目录前言一、搭建 Python 环境安装Python1. 找到官方网站2. 找到下载页面3. 双击安装包4. 运行 hello world安装PyCharm1. 找到官方网站2. 找到下载页面3. 双击安装包4. 运行 hello world创建一个项目选择项目所在的位置, 并选择使用的 Python 解释器.创建文件4. 编写代码5…

emoji与UTF-16、UCS-4、unicode的关系、原理和换算

emoji与UTF-16、UCS-4、unicode的关系、原理和换算 目录 emoji与UTF-16、UCS-4、unicode的关系、原理和换算 一、Unicode字符集概述 二、原理 1、UTF-16、UCS-4、unicode 2、emoji表情字符标准 3、关于肤色 一、Unicode字符集概述 https://en.wikipedia.org/wiki/Emoj…

【Python机器学习】标注任务与序列问题讲解(图文解释)

标注模型用于处理有前后关联关系的序列问题。在预测时&#xff0c;它的输入是一个观测序列&#xff0c;该观测序列的元素一般具有前后的关联关系。它的输出是一个标签序列&#xff0c;也就是说&#xff0c;标注模型的输出是一个向量&#xff0c;该向量的每个元素是一个标签&…

VScode ChatGPT 的中文插件安装使用

ChatGPT 的中文插件 由于官方服务对服务的封禁&#xff0c;大量国内代理服务全军覆没。开发者经过千辛万苦&#xff0c;找到了一个beta模型&#xff0c;目前作为 ChatGPT 正式服务上线前的过渡方案&#xff0c;供大家使用 插件安装后即处于”国内模式“&#xff0c;国内模式开…

艾美捷Annexin V-FITC凋亡检测试剂盒流式细胞术方案

FITC标记的重组人膜联蛋白V显示亮绿色荧光&#xff08;Ex&#xff08;max&#xff09;:488nm&#xff0c;Em&#xff08;max&#xff09;:530nm&#xff09;。 艾美捷Annexin V-FITC凋亡检测试剂盒化学性质&#xff1a; 应用&#xff1a;流式细胞术、荧光显微镜、荧光检测 应…

LncFinder | 非编码RNA的识别与分析神器!!!~

1写在前面 非编码RNA(ncRNAs), 是指不编码蛋白质的RNA。&#x1f617; 其中包括rRNA&#xff0c;tRNA&#xff0c;snRNA&#xff0c;snoRNA, lncRNA和miRNA等多种已知功能的RNA&#xff0c;还包括未知功能的RNA。&#x1f913; 长链非编码RNA&#xff08;lncRNA&#xff09;指的…

35. 搜索插入位置

给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2示例 2: 输入:…

机器学习100天(十六):016 逻辑回归损失函数

机器学习 100 天,今天讲的是:逻辑回归损失函数。 一、如何找到最佳分类直线 讲完了逻辑回归基本原理之后,我们再来思考一个非常关键的问题:就是如何找到最佳的分类直线呢? 如图中所示,如何判断这三条直线哪个更好?线性回归里,我们可以用均方误差作为损失函数,选择均…