当前位置: 首页 > article >正文

如何写一个转盘

需求描述

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

实现

思路

核心实现机制:

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

交互逻辑:

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

页面结构

什么是静态的?

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

什么是动态的?

  • 圆盘的旋转角度

什么是要算的?

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

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

实现机制

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

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

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

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

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

组件代码

<!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>

效果展示

在这里插入图片描述


http://www.kler.cn/a/446182.html

相关文章:

  • 【人工智能】用Python实现图卷积网络(GCN):从理论到节点分类实战
  • 音频接口:PDM TDM128 TDM256
  • 【HarmonyOS之旅】DevEco Studio的安装与环境配置
  • SQL语句整理五-StarRocks
  • OpenHarmony-4.HDI 框架
  • cenos如何升级git到2以上版本
  • 用C#绘制曼德布洛集分形
  • vue项目 中 asstes文件夹 与 static文件夹 的联系与区别
  • React 底部加载组件(基于antd)
  • String.prototype.padStart() 方法来实现日不足两位时补充零
  • 算法基础——递归
  • 最新 neo4j 5.26版本下载安装配置步骤【附安装包】
  • 梳理你的思路(从OOP到架构设计)_介绍GoF设计模式
  • 伪逆不能把矩阵变成单位阵
  • 【AI系列】Paddle Speech安装指南
  • Django REST framework(DRF)在处理不同请求方法时的完整流程
  • C#中的ConcurrentDictionary:线程安全实现与高效并发访问
  • 机器学习之拟合
  • 基于单片机的Wi-Fi控制智能窗帘设计
  • 深入理解 HTTP HEAD 请求:节省带宽、提高效率的秘密武器
  • flux模型的下载、配套及简易使用记录(ubuntu)
  • Laya ios接入goole广告,搭建环境 1
  • 一款轻量级的开源笔记服务软件
  • 常见八股文03
  • 怎么给git动图扣除背景?
  • #{ }和${ } 、参数处理