前言

很久没有写过小组件了,突然想做一个抽奖转盘,就花半天时间做一个,很简单

1.支持把一个圆盘分成n瓣。
2.实现转动动画。
3.弄个指针样式意思意思。
4.遇到抽奖的需求改吧改吧就能用了。

图是这样的

过分中分析的问题:
1.怎样根据数组长度把分好的扇形角度旋转到合适的位置。
2.扇形内部的元素也会跟着旋转,怎么矫正。

图片描述

代码

样式

@keyframes circle{
  from {transform: rotate(0)}
  to {transform: rotate(720deg)}
}
.turntable{
  height: 400px;
  width: 400px;
  margin: 0 auto;
  position: relative;
}

.content{
  height: 400px;
  width: 400px;
  position: relative;
  background-color: rgba(0, 0, 0, 0.3);
  border-radius: 50%;
  overflow: hidden;
  animation: circle 3s infinite;
  -webkit-animation:circle 3s infinite; /*Safari and Chrome*/
}
.box {
  height: 400px;
  width: 400px;
  position: absolute;
  left: 0;
  right: 0;
}
.item{
  position: absolute;
  height: 200px;
  width: 200px;
  left: 50%;
  top: 0;
  color: #fff;
}
.info{
  position: absolute;
  left: 5%;
  top: 50%;
}
.point{
  position: absolute;
  left: 50%;
  top: 50%;
  width: 30px;
  height: 30px;
  background-color: #ffd81a;
  border: 2px solid #ed1212;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
.arrow{
  position: absolute;
  left: 50%;
  top: 50%;
  height: 100px;
  width: 16px;
  transform: translate(-50%, -50%);
  background-color: #ffd81a;
  margin: -50px auto 0;
  box-shadow: 0px 0px 18px #7a7070;
}
.arrow::after{
  content: ' ';
  position: absolute;
  border-top: 8px solid transparent;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-bottom: 20px solid #ffd81a;
  top: -28px;
  left: 0px;

}

逻辑

import React from 'react';
import styles from './index.css';

import yay from '../assets/yay.jpg'

const gift: any[] = [
  {
    name: '1',
  },
  {
    name: '2'
  }, {
    name: '3'
  }, {
    name: '4'
  },
  {
    name: '5',
  },
  {
    name: '6'
  },
  {
    name: '7'
  },
  {
    name: '8'
  },
  {
    name: '9'
  },
  {
    name: '10'
  },
]
function getColor(): string {
  let colorValue = '0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f'
  let colorArray: string[] = colorValue.split(",")
  let color: string = '#'
  for (let i: number = 0; i < 6; i++) {
    color += colorArray[Math.floor(Math.random() * 16)]
  }
  return color
}

interface itemStyle {
  transform: string;
  backgroundColor: string;
}

function get_skew_deg(num: number): number {
  let average_deg: number = 360 / num

  let skew_deg: number = 90 - average_deg

  return skew_deg
}


function getItemStyle(num: number): itemStyle {

  let skew_deg: number = get_skew_deg(num)

  let translateY: number = Math.tan(skew_deg * 2 * Math.PI / 360) * 100

  let transform = `skew(0deg, -${skew_deg}deg) translateY(-${translateY}px)`

  return {
    transform,
    backgroundColor: getColor(),
  }
}

export default function () {
  return (
    <div className={styles.normal}>
      <div className={styles.turntable}>
        <div className={styles.content}>
          {gift.map((item, index) =>
            <div className={styles.box} key={item.name} style={{ transform: 'rotate(' + ((360 / gift.length) * index) + 'deg)' }}>
              <div className={styles.item} style={getItemStyle(gift.length)}>
                {item.name}
                <div className={styles.info} style={{ transform: `skew(0deg, ${get_skew_deg(gift.length)}deg) rotate(${(-(360 / gift.length) * index)}deg)` }}>
                  <img style={{ display: 'block', width: 60, height: 60, borderRadius: '50%' }} src={yay} alt="" />
                </div>
              </div>
            </div>)
          }
        </div>
        <div className={styles.arrow}></div>
        <div className={styles.point}></div>
      </div>
    </div>
  );
}

强子
335 声望10 粉丝

尽人事,安天命!