抽奖转盘实现

本文详细介绍了如何使用HTML、CSS和JavaScript实现一套抽奖转盘系统,包括转盘区域划分、动态创建元素、角度计算、弧形文字、概率计算以及动画效果。同时提供了JSON数据作为奖品配置,并展示了关键代码片段。
摘要由CSDN通过智能技术生成

这是我做的一套企业测试题 ,抽奖转盘,记录记录吧
在这里插入图片描述
测试题的要求如下:
在这里插入图片描述

第一步:画图
有三个大区域 最外层 中间的 里面的按钮区域;通过position定位将三个区域画好; 最里面的按钮的小图标用伪元素实现。(HTML CSS)
然后再就是文字描述和图片的摆放,这两个实现的思路是一样的,动态创建元素 循环添加 然后将元素append已经存在的div中(这个div需定位到按钮中间),因为每个文本和图片的位置是不一样的,他们是有规律的,分为5个区域,他们之间间隔的角度是360/5 就说明第一个旋转的角度是360/5*1 第二个旋转的角度就是(360/5)*2,以此类推;在循环中给span添加tranform:rotate(*deg)即可 还有就是弧形字体 通过引用arctext.js来实现(JS)
数据获取
通过script引入json数据即可
第二步:抽奖
思路
1.生成1-5的数字 此时概率是一样的
2.再随机生成1-100 根据步骤1生成的随机数判断1-5中某个区域的概率 例如:1的概率是35% 那么1-100随机生成的数字在1-35就算中奖
如果没有中奖,则继续从头开始随机生成1-5的数字 如此循环 有中奖的区域则退出
3.如果抽奖次数到达了30则直接随机生成,不按固定的概率来计算
动画
使用transition+transform就可以实现, 根据中奖的区域来rotate它的角度,然后弹出奖品对话框 同理 图片的路径也是根据中间的区域来读取的
基本思路就上面这些
我的代码实现如下
JSON

var itemdata = {
    itemlist: [{
            "txtDesc": "谢谢惠顾",
            "winningRate": 30,
            "imgSrc": "images/pic5.png"
        }, {
            "txtDesc": "小米手机",
            "winningRate": 10,
            "imgSrc": "images/pic2.png"
        }, {
            "txtDesc": "小米手环",
            "winningRate": 15,
            "imgSrc": "images/pic1.png"
        },
        {
            "txtDesc": "15元代金券",
            "winningRate": 20,
            "imgSrc": "images/pic3.png"
        }, {
            "txtDesc": "5元代金券",
            "winningRate": 25,
            "imgSrc": "images/pic4.png"
        }
    ]
}

HTML

<!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">
    <title>抽奖活动</title>
    <link rel="stylesheet" href="css/index.css">
    <script src="itemdata.json"></script>
</head>
<style>

</style>

<body>
    <div id="container" onclick="choujiang()">
        <div class="panel">
            <div class="btnPointer">
                <i>抽奖</i>
            </div>
            <div class="item">

            </div>

        </div>
        <div id="protxt" class="txtDesc">
        </div>
        <div class="line">

        </div>
    </div>
    <div id="tip">
        <p>抽奖结果:<span id="itemResult"></span></p>
        <p><img height="80" width="100" id="resultImg" src="" alt=""></p>
        <p>
            <button id="confirm" onclick="closeTip()">确认</button>
        </p>
    </div>
</body>
<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<script src="js/jquery.arctext.js"></script>
<script src="js/index.js"></script>

</html>

CSS

* {
    margin: 0;
    padding: 0;
}

#container {
    position: relative;
    margin-top: 20px;
    margin-left: 200px;
    height: 500px;
    width: 500px;
    background-color: rgb(250, 247, 156);
    border-radius: 50%;
    overflow: hidden
}

.panel {
    margin-top: 20px;
    /* margin-left: 200px; */
    margin: 25px;
    position: relative;
    height: 450px;
    width: 450px;
    background-color: #fff046;
    border-radius: 50%;
    z-index: 2;
}

.btnPointer {
    position: absolute;
    left: 167px;
    top: 167px;
    /* position: relative;
    z-index: 9999; */
    height: 110px;
    width: 110px;
    /* color: rgb(218, 35, 35); */
    line-height: 100px;
    font-size: 42px;
    padding: 6px;
    text-align: center;
    background-color: #f1741c;
    border-radius: 50%;
    border: 4px solid #f5b061;
    /* z-index: 100; */
    -webkit-text-stroke: 2px white;
    color: transparent;
    -webkit-text-fill-color: rgb(218, 35, 35);
    font-weight: 700;
}

.txtDesc {
    position: absolute;
    top: 250px;
    left: 250px;
    z-index: 100;
}

.txtDescStyle {
    display: block;
    /* margin-top: 10px; */
    position: absolute;
    top: -250px;
    left: -48px;
    padding-bottom: 476px;
    width: 100px;
    color: #f1741c
    /* transform: rotate(30deg);
    transform-origin: 'origin origin'; */
}

.item {
    position: absolute;
    top: 220px;
    left: 220px;
    /* z-index: 100; */
}

.line {
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: 2;
    /* border: 1px solid red; */
    width: 500px;
    height: 500px;
}

.item img {
    width: 100px;
    height: 100px;
    z-index: 4;
}

.lineStyle {
    z-index: 3;
    display: block;
    /* margin-top: 10px; */
    position: absolute;
    /* border: 1px solid red; */
    top: 30px;
    left: 250px;
    /* margin-bottom: 20px; */
    /* height: 300px; */
    width: 0.1px;
    border-bottom: 440px solid rgb(237, 128, 19);
    border-top: 0.1px solid transparent;
    /* border-left: 2px solid #fff046;
    border-right: 2px solid #fff046;
    /* border-top: 0px solid transparent; */
    /* position: relative; */
    /* transform: rotate(30deg);
    transform-origin: 'origin origin'; */
}

.imgStyle {
    display: block;
    /* margin-top: 10px; */
    position: absolute;
    /* border: 1px solid green; */
    /* border-left: 17px solid transparent;
    border-right: 17px solid transparent;
    border-bottom: 100px solid #f1741c; */
    top: -180px;
    left: -45px;
    padding-bottom: 280px;
    width: 100px;
    /* position: relative; */
    /* transform: rotate(30deg);
    transform-origin: 'origin origin'; */
}

.btnPointer::before {
    content: "";
    width: 0px;
    height: 0px;
    border-left: 12px solid transparent;
    border-right: 12px solid transparent;
    border-bottom: 20px solid #f1741c;
    position: absolute;
    top: -16px;
    left: 42%;
    z-index: 100;
}

#tip {
    width: 200px;
    /* border: 1px solid gray; */
    height: 160px;
    border-radius: 4px;
    position: absolute;
    top: 200px;
    left: 40%;
    box-shadow: 1px 1px 3px gray;
    padding: 10px;
    background: white;
    z-index: 10000;
    display: none;
}

#confirm {
    width: 80px;
    height: 36px;
    margin-top: 14px;
    background-color: greenyellow;
    border: none;
}

.pointerActive {
    transition: all;
    transition-duration: 3s;
    /* transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); */
    /* transform: rotateZ(calc(360deg * 3)); */
}

.activePoint {
    animation: run-rotate 3s ease-out 1;
}

@keyframes run-rotate {
    from {
        transform: rotateZ(0deg);
    }
    to {
        transform: rotateZ(calc(360deg * 3));
    }
}

JS

  //初始化轮盘
  init();

  $(function() {
      //字体弧形弯曲 
      $("#protxt span").show().arctext({
          radius: 170,
          dir: 1
      });
  })

  function init() {
      let txtDesc = document.getElementsByClassName("txtDesc")[0];
      let fragment = document.createDocumentFragment();
      let img = document.getElementsByClassName("item")[0];
      let fragmentimg = document.createDocumentFragment();

      let line = document.getElementsByClassName("line")[0];
      let fragmentline = document.createDocumentFragment();
      let list = itemdata.itemlist;
      for (let i = 0; i < 5; i++) {
          let descEle = document.createElement("span");
          let imgEle = document.createElement("img");
          let hrEle = document.createElement("div");
          //文本描述
          descEle.textContent = list[i].txtDesc;
          // 旋转的角度
          let deg = (360 / 5) * i;
          descEle.style.transform = `rotate(${deg}deg)`;
          descEle.className = "txtDescStyle";
          descEle.setAttribute("id", "span" + i);
          // descEle.style.transformOrigin = "origin origin";
          fragment.appendChild(descEle);
          // 抽奖图片
          imgEle.setAttribute("src", list[i].imgSrc);
          imgEle.className = "imgStyle";
          imgEle.style.transform = `rotate(${deg}deg)`;
          fragmentimg.appendChild(imgEle);

          // hrEle.textContent = "aa";
          hrEle.className = "lineStyle";
          hrEle.style.transform = `rotate(${deg}deg)`;
          fragmentline.appendChild(hrEle);

      };
      txtDesc.appendChild(fragment);
      img.appendChild(fragmentimg);
      line.appendChild(fragmentline);
  }
  let count = 0;
  //抽奖
  function choujiang() {
      //产生随机数 1-5
      //概率
      //1.生成1-5的数字 此时概率是一样的
      //2.再随机生成1-100 根据步骤1生成的随机数判断1-5中某个区域的概率 例如:1的概率是35% 那么1-100随机生成的数字在1-35就算中奖
      //  如果没有中奖,则继续从头开始随机生成1-5的数字 如此循环 有中奖的区域则退出
      //3.如果抽奖次数到达了30则直接随机生成,不按固定的概率来计算
      let txtTip = "",
          imgIndex = 0;
      let list = itemdata.itemlist;
      if (count <= 30) {
          let firstRandom = rand(1, 5);
          // if (firstRandom = 1) {
          //     let ratenum = list[0].winningRate;
          //     //再随机生成1-100 判断ratenum是否=
          //     let secondRandom = rand(1, 100);
          //     if (secondRandom <= ratenum) {
          //         txtTip = list[0].txtDesc;
          //     }
          // }
          while (txtTip == "") {
              for (let i = 1; i <= 5; i++) {
                  // alert(firstRandom);
                  if (firstRandom = i) {
                      let ratenum = list[i - 1].winningRate;
                      //再随机生成1-100 判断ratenum是否=
                      let secondRandom = rand(1, 100);
                      if (secondRandom <= ratenum) {
                          txtTip = list[i - 1].txtDesc;
                          imgIndex = i - 1;
                          break;
                      }
                  }
              }
              if (txtTip == "") {
                  firstRandom = rand(1, 5);
              }
          }
          count++;
      } else {
          //足够次数的抽奖后,抽奖结果分布应当趋近于中奖概率
          let randomNum = rand(1, 5);
          for (let i = 1; i <= 5; i++) {
              if (randomNum = i) {
                  txtTip = list[i - 1].txtDesc;
                  imgIndex = i - 1;
              }
          }
      }
      //轮盘旋转显示结果
      let pointDeg = (360 / 5) * imgIndex;
      let pointer = document.getElementsByClassName("btnPointer")[0];
      //   pointer.className = "activePoint btnPointer";
      let rotateDeg = (360 * 3) + pointDeg;
      pointer.style.transform = `rotate(${rotateDeg}deg)`;
      pointer.className = "btnPointer pointerActive";
      //   pointer.style.transform = `rotate(${pointDeg}deg)`;
      //弹出图片
      let resultimg = document.getElementById("resultImg");
      let itemResult = document.getElementById("itemResult");
      resultimg.setAttribute("src", list[imgIndex].imgSrc);
      itemResult.textContent = txtTip;
      //显示图片
      setTimeout(function() {
          document.getElementById("tip").style.display = "block";
      }, 3000);
      // alert(txtTip + " count:" + count);
  }

  function rand(m, n) {
      return Math.ceil(Math.random() * (n - m + 1) + m - 1)
  }
  // window.onload = function() {
  //     document.getElementsByClassName("btnPointer")[0].addEventListener("click", function(e) {
  //         // e.preventDefault();
  //         alert("z");
  //     }, false)
  // }
  // 关闭弹窗
  function closeTip() {
      document.getElementById("tip").style.display = "none";
      let pointer = document.getElementsByClassName("btnPointer")[0];
      pointer.style.transform = `rotate(0deg)`;
      pointer.className = "btnPointer";

  }

  console.log(itemdata.itemlist);

如果对你有用的话就点个赞吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值