HTML翻牌器:用CSS和HTML元素创造动态数字展示

news2024/9/23 6:48:27

HTML翻牌器:用CSS和HTML元素创造动态数字展示

前言

翻牌器是一种数字动态展示形式,在生活中常见的例如翻牌计分、翻牌时钟等。

之所以以翻牌的形式是因为其物理设计的原因使其只能滚动翻牌展示数字,在电子显示设备不普及时,使用场景较广。

现在电子屏可以很方便的去切换数字,翻牌器已经渐渐淡出我们的生活,但是这样的表现形式在某些情况下更能突出数字的变化、丰富页面的内容,使其更具有吸引力。

那么今天我们就来聊一聊怎样在HTML中使用CSS + HTML元素制作一个翻牌器。

翻牌器的机制

翻牌器数字翻牌是通过翻动展示一张卡片不同的面而实现的。如下图所示:

那么,这样来说的话,一个数字其实是由一张卡片的正面及它前一张卡片的背面组成,然后多张卡片组成一个循环,依次滚动就能实现展示数字。

HTML中实现

为了实现翻牌器的效果,那么我们需要用到CSS 3D 中的 rotateX 加上景深来展现出3D 的翻动效果。

除此之外,我们还需要将数字卡片进行上下分块,这个办法有很多,这里我们是使用CSS 中的 clipPath 属性,这样能保证数字的上部分和下部分能在拼接时能完全对齐且居中。

HTML中元素是没有正面和背面的概念的,我们没办法使用背面,那么只能通过两个正面去模拟一个背面加一个正面,然后让其滚动。单个的数字就如下图所示:

image

接下来就是滚动的问题,在CSS 3D 中,rotateX 配合动画就能实现上下的翻动效果。

多次滚动其实就是依次播放动画,这里会有一个问题,当我们快速翻动卡片时,上面的部分后出现的内容在层级上需要在后面,但是翻滚到下面部分时,后面的内容在层级上需要在前面。

我们通过 z-index 去控制会很麻烦。那我们应该怎么去做才好呢?

HTML中我们是没办法去使用背面的,那我们的卡片进行翻滚是在上部分仅需注意正面,在下部分只要注意反面(卡片对应的反面,用元素的正面来表示),当上部分结束后再插入下部分,这样层级就能从上下区分开。

我们仅需关注单个数字再进行组合即可实现多位的翻牌器。

而且在动画播放结束时,我们只需要保证上下各部分有一张卡片能正确展示即可,多余的内容我们可以去除,节省空间和提高效率。基本翻动流程如下:

  1. 创建卡片的正面和背面。
  2. 使用 clipPath 将卡片分割为上下两部分。
  3. 通过 rotateX 和动画实现翻牌效果。
  4. 管理卡片的层级和顺序,确保动画流畅。

基础HTML和CSS代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      width: 100vw;
      height: 100vh;
      overflow: hidden;
      background: #000;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .wrap {
      height: 120px;
      line-height: 120px;
    }
    .filper-item {
      position: relative;
      color: blueviolet;
      font-size: 100px;
      font-weight: bold;
      perspective: 700px;
    }
    .card-item {
      top: 0;
      left: 0;
      position: absolute;
      background: #fff;
    }
  </style>
</head>
<body>
  <div id="wrap" class="wrap"></div>

  <script>
    // JavaScript代码
  </script>
</body>
</html>

JavaScript实现

JavaScript中,我们创建一个 FilperItem 类来管理翻牌器的逻辑。这个类负责创建卡片、初始化DOM结构、以及实现增加和减少数字的动画效果。

class FilperItem {
  constructor(wrap) {
    this.num = 0;
    this.initDom();
    wrap.appendChild(this.el);
  }

  createCard(type, num, fixed) {
    const el = document.createElement('div');
    el.className = 'card-item';
    const innerText = num;
    if (fixed) {
      el.style.position = 'relative';
    }
    // 上下的 clipPath
    const clipPath = type === 'top' ? 'polygon(0 0, 100% 0%, 100% 50%, 0 50%)' : 'polygon(0 50%, 100% 50%, 100% 100%, 0% 100%)';
    el.innerText = innerText;
    el.style.clipPath = clipPath;
    return el;
  }

  initDom() {
    const el = document.createElement('div');
    el.className = 'filper-item';
    const top = this.createCard('top', 0, false);
    const bottom = this.createCard('bottom', 0, true);
    // 添加默认的上下
    el.appendChild(top);
    el.appendChild(bottom);
    this.el = el;
    this.top = top;
    this.bottom = bottom;
  }

  increase(to = undefined) {
    const { num, top, bottom, el } = this;
    let txt = to ?? (num + 1) % 10;
    if (txt === num) return;
    // 动画
    const animate = {
      zIndex: [1, 1],
      transform: ['rotateX(0)', 'rotateX(-90deg)'],
      offset: [0, 1]
    };
    const animate1 = {
      zIndex: [1, 1],
      transform: ['rotateX(90deg)', 'rotateX(0deg)'],
      offset: [0, 1]
    };
    const animateOption = {
      duration: 500
    };
    const t = this.createCard('top', num);
    el.insertBefore(t, el.childNodes[1]);
    const ta = t.animate(animate, animateOption);
    setTimeout(() => {
      top.innerText = txt;
    });
    // 上部分动画完成后插入下部分并执行动画
    ta.onfinish = () => {
      el.removeChild(t);
      const b = this.createCard('bottom', txt);
      el.appendChild(b);
      const ba = b.animate(animate1, animateOption);
      ba.onfinish = () => {
        bottom.innerText = txt;
        el.removeChild(b);
      };
    };
    this.num = txt;
  }

  reduce(to = undefined) {
    const { num, top, bottom, el } = this;
    let txt = to ?? (num + 9) % 10;
    if (txt === num) return;
    const animate = {
      zIndex: [1, 1],
      transform: ['rotateX(-90deg)', 'rotateX(0)'],
      offset: [0, 1]
    };
    const animate1 = {
      zIndex: [1, 1],
      transform: ['rotateX(0deg)', 'rotateX(90deg)'],
      offset: [0, 1]
    };
    const animateOption = {
      duration: 500
    };
    const b = this.createCard('bottom', num);
    if (bottom.nextElementSibling) {
      el.insertBefore(b, bottom.nextElementSibling);
    } else {
      el.appendChild(b);
    }

    const ba = b.animate(animate1, animateOption);
    setTimeout(() => {
      bottom.innerText = txt;
    });
    ba.onfinish = () => {
      el.removeChild(b);
      const t = this.createCard('top', txt);
      el.insertBefore(t, bottom);
      const ta = t.animate(animate, animateOption);
      ta.onfinish = () => {
        top.innerText = txt;
        el.removeChild(t);
      };
    };
    this.num = txt;
  }

  filper(next, dir = 'increase') {
    switch (dir) {
      case 'increase': {
        this.increase(next);
        break;
      }
      case 'reduce': {
        this.reduce(next);
      }
    }
  }
}

使用方式:


const wrap = document.querySelector('#wrap');
const f = new FilperItem(wrap);

window.f = f;

window.onkeydown = (e) => {
  if (e.code === 'ArrowDown') {
    f.reduce();
  } else if (e.code === 'ArrowUp') {
    f.increase();
  } else if (/^\d$/.test(e.key)) {
    f.filper(Number(e.key));
  }
};

效果如下

总结

通过上述步骤,我们已经在 HTML 中使用 CSSJavaScript 创建了一个基础的翻牌器。

这个翻牌器可以响应键盘事件,实现数字的增加和减少。

虽然这里的实现相对简单,但它展示了如何利用现代Web技术来模拟传统翻牌器的动态效果。

随着技术的进一步发展,我们可以在此基础上添加更多功能,如动画效果的优化、多数字支持等,以创造出更加炫酷的效果。

– 欢迎点赞、关注、转发、收藏【我码玄黄】,各大平台同名。

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

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

相关文章

PMBOK® 第六版 估算活动持续时间

目录 读后感—PMBOK第六版 目录 在项目管理中&#xff0c;尤其是在软件开发这样的复杂项目中&#xff0c;工作内容是多种多样的。从需求分析、设计、编码到测试和部署&#xff0c;每个阶段都有其独特的挑战和不确定性。 没有人能独自完成所有估算工作并做到绝对精准。估算涉及…

【Unity Shader】Special Effects(九)Vortex 旋涡(UI)

源码:[点我获取源码] 索引 Vortex 旋涡思路分析旋涡中心旋涡旋转旋涡强度旋涡动画Vortex 旋涡 旋涡效果可以将一张图像以指定点作为旋涡中心,呈顺时针旋涡动画效果,使用动画播放器: 思路分析 首先,旋涡特效的核心也即是旋转(特别是uv坐标的旋转); 在此基础上,旋涡中…

Vue(15)——组合式API②

生命周期函数 选项式组合式beforeCreate/createdsetupbeforeMountonBeforeMount mountedonMounedbeforeUpdateonBeforeUpdateupdatedonUpdatedbeforeUnmountonBeforeUnmountunmountedonUnmounted 父子通信 父传子基本思想&#xff1a; 父组件中给子组件绑定属性…

Vue Devtools -----一条龙安装教程 + 解决安装使用过程的一些问题

一条龙安装教程&#xff08;首次 安装看这里&#xff09; 点击下方网址 进入下载页面 安装 |Vue 开发工具 (vuejs.org)https://devtools-v6.vuejs.org/guide/installation.html 选择适合自己浏览器的版本 以Edge为例&#xff0c;点击下载即可 我以为已经下载过了&#xff0c;…

BUUCTF-MISC-数据包中的线索

下载题目文件&#xff0c;解压发现是一段流量包 使用Wireshark打开 首先过滤HTTP数据流 然后追踪HTTP数据流 通过追踪数据流可以发现 流7 当中有一段base64编码&#xff0c;我们尝试解码 base64基本特征 Base64编码只包含64个字符&#xff1a;大写字母&#xff08;A-Z&#x…

计算机网络笔记002

### 课堂讨论对话 **学生A**: 老师&#xff0c;计算机网络的组成是怎样的&#xff1f;&#x1f914; **老师**: 非常好的问题&#xff01;计算机网络主要由硬件、软件和通信协议三部分组成。我们先从硬件开始讨论吧。 **学生B**: 硬件包括哪些设备呢&#xff1f;&#x1f60…

cmd快速进入文件夹目录下

首先&#xff0c;将文件夹直接点击左键拖动至cmd窗口中&#xff0c;就可以得到目录路径。 还有就是&#xff0c;在命令行直接敲入D:或者C:就可以在磁盘之间进行转换&#xff0c;注意冒号不要丢。 再有&#xff0c;如果进入某磁盘中的一个文件夹&#xff0c;使用cd命令。路径获取…

zabbix email 告警

配置媒介、触发器动作&#xff08;动作、操作&#xff09; 为用户 定义媒体&#xff0c;比如电子邮件地址 动作 - 条件

[图解]静态关系和动态关系

1 00:00:01,060 --> 00:00:04,370 首先我们来看静态关系和动态关系 2 00:00:06,160 --> 00:00:10,040 我们要尽量基于静态关系来建立动态关系 3 00:00:11,740 --> 00:00:13,740 不能够在没有这个的基础上 4 00:00:14,220 --> 00:00:17,370 没有这个的情况下就胡…

2024PHP彩虹工具网源码一个多功能工具箱程序支持72种常用站长和开发等工具

安装&#xff1a; PHP>7.4 伪静态设置Thinkphp 设置/public为网站运行目录 访问你的域名/install进行安装即可 安装扩展 sg11 &#xff0c;fileinfo &#xff0c; ionCube 常用功能 站长工具&#xff1a;ICP备案查询、IP地址查询、域名Whios查询、腾讯域名拦截查询、Mysql…

828华为云征文 | 构建高效搜索解决方案,Elasticsearch Kibana的完美结合

前言 构建高效搜索解决方案&#xff0c;FlexusX服务器与Elasticsearch & Kibana的完美结合&#xff0c;为企业带来云端搜索新体验。FlexusX实例以其卓越性能与灵活扩展性&#xff0c;确保高并发搜索的流畅运行。部署Elasticsearch&#xff0c;享受分布式搜索的精准与快速&a…

从Yargs源码学习中间件的设计

yargs中间件介绍 yargs 是一个用于解析命令行参数的流行库&#xff0c;它能帮助开发者轻松地定义 CLI&#xff08;命令行接口&#xff09;&#xff0c;并提供参数处理、命令组织、help文本自动生成等功能。今天我们来学习一下它对中间件的支持。 中间件的API详细信息&#xff0…

Python | Leetcode Python题解之第430题扁平化多级双向链表

题目&#xff1a; 题解&#xff1a; class Solution:def flatten(self, head: "Node") -> "Node":def dfs(node: "Node") -> "Node":cur node# 记录链表的最后一个节点last Nonewhile cur:nxt cur.next# 如果有子节点&#…

旋转机械故障数据集 全网首发

旋转机械故障 数据集 11G资料 泵、齿轮箱、电机、流量、液压系统、轴承(西储大学、辛辛那提大学、FEMTO、MOSFET)、PHM08挑战数据集、我闪发动机降级模拟数据集、铣床等 旋转机械故障数据集 数据集描述 该数据集是一个综合性的旋转机械故障检测和诊断数据集&#xff0c;旨在…

【ChatGPT】提示词助力广告文案、PPT制作与书籍推荐的高效新模式

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;高效广告推销文案提示词使用方法 &#x1f4af;AI自动生成PPT全流程提示词使用方法 &#x1f4af;精选书籍推荐爆款文案提示词使用方法 &#x1f4af;小结 &#x1f4af;…

【VUE3.0】动手做一套像素风的前端UI组件库---Radio

目录 引言做之前先仔细看看UI设计稿解读一下都有哪些元素&#xff1a;参考下成熟的组件库&#xff0c;看看还需要做什么&#xff1f; 代码编写1. 设计group包裹选项的组件group.vueitem.vue 2. 让group的v-model和item的value联动起来3. 完善一下item的指示器样式4. 补充禁用模…

【测试】——JUnit

&#x1f4d6; 前言&#xff1a;JUnit 是一个流行的 Java 测试框架&#xff0c;主要用于编写和运行单元测试&#xff0c;用来管理测试用例。本文采用JUnit 5 目录 &#x1f552; 1. 添加依赖&#x1f552; 2. 注解&#x1f558; 2.1 Test&#x1f558; 2.2 BeforeAll AfterAll&…

【Docker】基于docker compose部署artifactory-cpp-ce服务

基于docker compose部署artifactory-cpp-ce服务 1 环境准备2 必要文件创建与编写3 拉取镜像-创建容器并后台运行4 访问JFog Artifactory 服务 1 环境准备 docker 以及其插件docker compose &#xff0c;我使用的版本如下图所示&#xff1a; postgresql 的jdbc驱动, 我使用的是…

【图像检索】基于纹理(LBP)和形状特征的图像检索,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于纹理(LBP)和形状特征&#xff08;hu特征&#xff09;的图像检索&#xff0c;用m…

力扣206.反转链表

力扣《反转链表》系列文章目录 刷题次序&#xff0c;由易到难&#xff0c;一次刷通&#xff01;&#xff01;&#xff01; 题目题解206. 反转链表反转链表的全部 题解192. 反转链表 II反转链表的指定段 题解224. 两两交换链表中的节点两个一组反转链表 题解325. K 个一组翻转…