如何写一个转盘

需求描述

  • 实现一个圆形转盘组件,转盘上的元素均匀分布,同时保持转盘元素的水平轴始终指向圆心。保证转盘最左边的元素是水平放置,正常展示。
  • 点击地下一排按钮,则转盘上对应的元素转到最左边。

实现

思路

核心实现机制:

  • 外部的容器,也就是圆周,采用相对定位
  • 每个数字块的定位采用绝对定位 + transform,旋转好角度后有序放在圆周上

交互逻辑:

  • 点击底部按钮时,计算目标数字所需旋转角度
  • 转盘通过 CSS transform: rotate() 实现整体旋转
  • 通过 CSS transition 实现平滑旋转动画

页面结构

什么是静态的?

  • 转盘的形状
  • 转盘元素的形状
  • 转盘元素相对于圆盘水平线的角度

什么是动态的?

  • 圆盘的旋转角度

什么是要算的?

  • 圆盘的旋转角度
  • 转盘元素相对于圆盘水平线的角度

动态的和要算的要写成变量或者方法

实现机制

不要去想转了 多少度,不要想成计算;而是应该每个位置对应一个唯一的旋转角度,要想成映射

计算转盘元素相对于圆盘水平线的角度,包含三个关键步骤:

  • rotate(角度) - 按序分布在圆周上
  • translate(-150px) - 将数字移到圆周上,这里应为要保证最左边的元素是我们要展示的元素,所以是负数
  • translate(-150px) translate(-50%)确保圆盘元素的中心在圆周的上
javascript 复制代码
// 计算每个数字块的位置和角
getItemStyle(index) {
  const anglePerSector = 360 / this.totalSectors;
  const rotateAngle = index * anglePerSector;
  return {
    transform: `rotate(${rotateAngle}deg) translate(-150px) translate(-50%) translateY(-50%)`,
  };
},

旋转转盘的方法,也就是要算出目标位置对应的角度是多少

java 复制代码
// 计算按钮点击后转盘的旋转角度
rotateToNumber(index) {
    const anglePerSector = 360 / this.totalSectors;
    const targetAngle = index * anglePerSector;
    // 为了让目标数字转到最左边,我们需要相应调整角度
    this.rotation = -targetAngle;
},

组件代码

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="wheel-container">
    <!-- 转盘 -->
    <div class="wheel" :style="{ transform: `rotate(${rotation}deg)` }">
      <div v-for="(item, index) in numbers" :key="index" class="wheel-item" :style="getItemStyle(index)">
        {{ item }}
      </div>
    </div>

    <!-- 数字按钮 -->
    <div class="buttons">
      <button v-for="(item, index) in numbers" :key="index" @click="rotateToNumber(index)">
        {{ item }}
      </button>
    </div>
  </div>
</div>
</body>
<script>
  let vm = new Vue({
    el: "#vue_root",
    data() {
      return {
        numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9], // 转盘上的数字
        rotation: 0, // 转盘的旋转角度
        totalSectors: 9, // 转盘分为9个部分
      };
    },
    methods: {
      // 计算按钮点击后转盘的旋转角度
      rotateToNumber(index) {
        const anglePerSector = 360 / this.totalSectors;
        const targetAngle = index * anglePerSector;
        // 为了让目标数字转到最左边,我们需要相应调整角度
        this.rotation = -targetAngle;
      },
      // 计算每个数字块的位置和角
      getItemStyle(index) {
        const anglePerSector = 360 / this.totalSectors;
        const rotateAngle = index * anglePerSector;
        return {
          transform: `rotate(${rotateAngle}deg) translate(-150px) translate(-50%) translateY(-50%)`,
        };
      },
    },
  })
</script>
<style>
  .wheel-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    margin-top: 50px;
  }

  .wheel {
    width: 300px;
    height: 300px;
    border-radius: 50%;
    border: 2px solid #000;
    position: relative;
    /*left: 50%;*/
    margin-bottom: 20px;
    transition: transform 1s ease-in-out; /* 转盘旋转时的动画效果 */
  }

  .wheel-item {
    position: absolute;
    top: 50%;
    left: 50%;
    transform-origin: 0 0; /* 以左上角为原点进行旋转 */
    width: 30px;
    height: 30px;
    background-color: #f1c40f;
    text-align: center;
    line-height: 30px;
    border-radius: 50%;
  }

  .buttons {
    display: flex;
    justify-content: center;
  }

  button {
    margin: 0 5px;
    padding: 10px 20px;
    background-color: #3498db;
    color: white;
    border: none;
    cursor: pointer;
  }

  button:hover {
    background-color: #2980b9;
  }
</style>
</html>

效果展示

相关推荐
_阿南_1 小时前
项目中新增给AI制定的代码规范
前端·程序员
名字还没想好☜2 小时前
React 实现暗黑模式切换:localStorage 持久化、SSR 首屏闪烁与跟随系统主题
前端·javascript·react.js·ecmascript·react·next.js
kruptos2 小时前
分布式系统怎么“选主“?Raft 共识一次讲清
开发语言·分布式·php·共识算法
吴声子夜歌2 小时前
ApacheCommons——commons-cli(命令行参数解析)
java·开发语言·apache
console.log('npc')3 小时前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
benchmark_cc3 小时前
REST API 和 Python SDK 应该怎么选?量化交易数据接口选型实战
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
王的宝库3 小时前
Go 项目结构:从单文件到标准工程布局
开发语言·后端·golang
Tairitsu_H4 小时前
[C++] 深入理解红黑树:封装set与map
开发语言·c++·set·map·红黑树·模拟实现
泡海椒4 小时前
JQuick-Curl 性能分析:并发场景下的性能表现与调优,第三方接口调用不只要快写也要稳跑
java·开发语言·okhttp
小智老师PMP4 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理