如何写一个数字老虎机滚轮

需求描述

写一个数字滚轮,实现类似老虎机的效果,可以指定数字

实现思路

这个数字滚动组件的核心实现思路可以概括为:

  1. 视觉原理
  • 每个数字位用一个固定高度的容器,通过 overflow: hidden 只显示一个数字
  • 容器内部包含完整的 0-9 序列,通过上下平移显示不同数字
  • 重复放置首尾数字(0)实现无缝滚动效果
  1. 动画实现
  • 使用 CSS animation 实现两个关键动画:
    • 滚动中:无限循环向上平移实现滚动效果
    • 停止时:精确平移到目标数字的位置
  1. 控制逻辑
  • Vue 管理组件状态(rolling)控制动画切换
  • 通过 CSS 变量(--num)动态计算每个数字的最终停止位置
  • 使用 setTimeout 控制滚动持续时间

实现细节

页面结构

每一位数字都是这么个结构

滚动效果的实现

所谓的滚动其实就是那一长溜的数字不断重复从上到下或者从下到上这个操作,所以外层realtive,内层absolute,加上动画

那一长溜的数字最终的停止位置是需要根据这一位上的显示数字来确定的,因此需要动态算出来,在这个组件里面是下面标黄的来算

javascript 复制代码
<div
              :class="['TigerNumbers', rolling ? 'rolling' : 'stop']"
              :style="{ '--num': ((n || 10) - 10) * 1.5 + 'em' }"
      >

动画分为两种:

  • 滚动的动画。translateY从0到-100%,不断循环
css 复制代码
@keyframes NumberRoll {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-100%);
  }
}
  • 最终的停止动画。就是translateY从0到算出来的要停下来的位置
css 复制代码
@keyframes NumberStop {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(calc(var(--num)));
  }
}

数据设计

  • 用一个数组来存要显示的数字
  • 用一个rolling变量来标记现在是滚动状态还是停止滚动状态

组件代码

vue 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <script src="./js/vue.min.js"></script>
    <title>Title</title>
  </head>
  <body>
    <div id="vue_root">
      <div class="Tiger">
        <div v-for="(n, index) in numbers" :key="index" class="TigerItem">
          <div
            :class="['TigerNumbers', rolling ? 'rolling' : 'stop']"
            :style="{ '--num': ((n || 10) - 10) * 1.5 + 'em' }"
            >
            <div>0</div>
            <div>9</div>
            <div>8</div>
            <div>7</div>
            <div>6</div>
            <div>5</div>
            <div>4</div>
            <div>3</div>
            <div>2</div>
            <div>1</div>
            <div>0</div>
          </div>
        </div>
      </div>
    </div>
  </body>
  <script>
    let vm = new Vue({
      el: "#vue_root",
      data() {
        return {
          rolling: true,
          numbers: [5, 3, 8], // 你可以根据需要修改数字数组
          delaySec: 2, // 你可以根据需要修改 delaySec 的默认值
        };
      },
      mounted() {
        setTimeout(() => {
          this.rolling = false;
        }, this.delaySec * 1000);
      },
    })
  </script>
  <style>
    .Tiger {
      display: flex;
    }

    .TigerItem {
      width: 1em;
      height: 1.5em;
      position: relative;
      overflow: hidden;
      background-color: lightgreen;
      margin-right: 0.5em;
    }

    .TigerNumbers {
      position: absolute;
      width: 100%;
      text-align: center;
    }

    .TigerNumbers > div {
      line-height: 1.5em;
      height: 1.5em;
    }

    .TigerNumbers.rolling {
      animation: NumberRoll 0.3s infinite linear;
    }

    .TigerNumbers.stop {
      animation: NumberStop 0.6s forwards;
    }

    @keyframes NumberRoll {
      0% {
        transform: translateY(0);
      }
      100% {
        transform: translateY(-100%);
      }
    }

    @keyframes NumberStop {
      0% {
        transform: translateY(0);
      }
      100% {
        transform: translateY(calc(var(--num)));
      }
    }
  </style>
</html>

效果演示

相关推荐
codelang1 小时前
Cline + MCP 开发实战
前端·后端
好_快3 小时前
Lodash源码阅读-memoizeCapped
前端·javascript·源码阅读
好_快3 小时前
Lodash源码阅读-toString
前端·javascript·源码阅读
好_快3 小时前
Lodash源码阅读-memoize
前端·javascript·源码阅读
excel3 小时前
webpack 核心编译器 十四 节
前端
excel3 小时前
webpack 核心编译器 十三 节
前端
腾讯TNTWeb前端团队10 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰13 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪14 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪14 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试