Skip to content

html转盘抽奖,conic-gradient+transform,复制即用~

首先了解下conic-gradient

CSS 函数 conic-gradient() 创建一个由渐变组成的图像,渐变的颜色围绕一个中心点旋转(而不是从中心辐射);用conic-gradient()即可画出转盘扇形布局,如下

html
<!-- 由此我们可以画出4块扇形 -->
<div style="margin: 0 auto">
      <div class="conic-gradient"></div>
 </div>
<style>
	.conic-gradient {
        width: 200px;
        height: 200px;
        border-radius: 9999px;
        background-image: conic-gradient(
          green 0deg,
          green 90deg,
          red 90deg,
          red 180deg,
          pink 180deg,
          pink 270deg,
          blue 270deg,
          blue 360deg
        );
      }
</style>

如图: shanxing.png

transfrom

如此我们可以借助transfrom:rotate旋转+transition过渡+时间缓动函数写一个转盘旋转效果;

html
<!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>
      .conic-gradient {
        width: 200px;
        height: 200px;
        border-radius: 9999px;
        background-image: conic-gradient(
          green 0deg,
          green 90deg,
          red 90deg,
          red 180deg,
          pink 180deg,
          pink 270deg,
          blue 270deg,
          blue 360deg
        );
        transition: transform 3s cubic-bezier(0.25, 0.1, 0.25, 1);
        transform: rotate(0deg);
      }
    </style>
  </head>
  <body>
    <div
      style="
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: center;
      "
    >
      <div class="conic-gradient"></div>
      <button style="margin-top: 50px">旋转1800度</button>
    </div>
    <script>
      const btn = document.querySelector("button");
      btn.addEventListener("click", () => {
        const conic = document.querySelector(".conic-gradient");
        conic.style.transform = "rotate(1800deg)";
      });
    </script>
  </body>
</html>

如图所示,现在一个简单的转盘旋转效果就完成啦~ chrome_QrYHkuUXfD.gif

接着定义抽奖数组,初始化转盘

js
//抽奖数组
let prizes = [
      { name: 'iPhone 15 Pro', imageUrl: '📱', uid: '1' },
      { name: 'iPad Air', imageUrl: '📱', uid: '2' },
      { name: 'AirPods Pro', imageUrl: '🎧', uid: '3' },
      { name: 'Apple Watch', imageUrl: '⌚', uid: '4' },
      { name: 'MacBook Pro', imageUrl: '💻', uid: '5' },
      { name: '现金红包', imageUrl: '💰', uid: '6' },
      { name: '优惠券', imageUrl: '🎫', uid: '7' },
      { name: '谢谢惠顾', imageUrl: '😭😭', uid: '0' }
    ]
//在定义几个需要的变量
/* 旋转角度 */
let rotateDeg = 0;
/* 是否正在旋转 */
let isSpinning = false;
/* 是否正在过渡 */
let transitionActive = true;

//初始化转盘
function initWheel() {
  const wheel = document.getElementById('wheel');
  const prizeCount = prizes.length;
  const anglePerPrize = 360 / prizeCount;
    
  wheel.innerHTML = '';

   //根据奖品数组,生成奖品子元素
   prizes.forEach((prize, idx) => {
        const prizeElement = document.createElement('div');
        prizeElement.className = 'prize';
        prizeElement.style.transform = `rotate(${idx * 360 / prizes.length + 360 / prizes.length / 2}deg) translateY(-180px)`;
        prizeElement.innerHTML = `
                    <div>${prize.name}</div>
                    <div class="prize-icon">${prize.imageUrl}</div>
                `;
        wheel.appendChild(prizeElement);
      });
      // 更新转盘样式 
      updateWheelStyle();
    }

    // 计算转盘样式
    function getWheelStyle() {
      //计算扇形角度
      const deg = 360 / prizes.length;
      //扇形颜色,这里我复用了3个颜色
      const colors = ['#fff5e1', '#ffbb93', '#ffe4ca'];
      //拼接conic-gradient
      const prizesGradient = prizes.map((item, idx) => {
        return `${colors[idx > 2 ? idx % 3 : idx]} ${idx * deg}deg ${(idx + 1) * deg}deg`;
      }).join(',');

      return {
        transform: `rotate(${rotateDeg}deg)`,
        transition: transitionActive ? 'transform 3s cubic-bezier(0.25, 0.1, 0.25, 1)' : 'none',
        background: `conic-gradient(${prizesGradient})`
      };
    }

    // 更新转盘样式
    function updateWheelStyle() {
      const wheel = document.getElementById('wheel');
      const style = getWheelStyle();
      wheel.style.transform = style.transform;
      wheel.style.transition = style.transition;
      wheel.style.background = style.background;
    }

初始化后样式如图: a.png

抽奖函数

js
function startLottery() {
      if (isSpinning) return;
      isSpinning = true;

      /* 模拟接口请求 */
      setTimeout(() => {
        /* 中奖下标 */
        const prizeIndex = Math.floor(Math.random() * prizes.length);
        /* 奖品数量 */
        const prizeCount = prizes.length;

        /* 每个奖品的角度 */
        const anglePerPrize = 360 / prizeCount;
        /* 旋转4圈 */
        const baseRotate = 360 * 4;
        /* 目标角度,正好旋转到奖品中间 */
        const targetDeg = baseRotate + (360 - prizeIndex * anglePerPrize) - anglePerPrize / 2
        /* 取消过渡 */
        transitionActive = false;
        /* 旋转角度 */
        rotateDeg = rotateDeg % 360;
        /* 更新样式 */
        updateWheelStyle();
        setTimeout(() => {
          transitionActive = true;
          /* 更新样式-开始过渡 */
          updateWheelStyle();
          setTimeout(() => {
            /* 中奖奖品角度 */
            rotateDeg = targetDeg;
            /* 更新样式-旋转到目标角度 */
            updateWheelStyle();
            setTimeout(() => {
              /* 过渡时间是3秒,所以三秒后再赋值为false,抽奖完成 */
              isSpinning = false;
              console.log(prizes[prizeIndex])
              alert(prizes[prizeIndex].name)
            }, 3000);
          }, 20);
        }, 300);
      }, 500)
    }

开抽~😭😭😭谢谢惠顾

chou.gif