前言
- 转盘游戏是经常要制作的小游戏,看别人用渐变实现很有意思,一个转盘也是很复杂的。
- 本文实现参考了徐小夕大佬的公众号。
样式部分
- 单个扇形实现:利用border-radius和linear-gradient来渐变。
- 做扇形还有一种思路,就是先做正方形,然后用skew进行形变,变成菱形,再定位到相应位置,拿容器overflow hidden一下就行。
- 这里采用linear-gradient,另外上面那个指针,我是用宽高为0的div的边框做的。
效果:
$pieceHeight = 300px //这个可以控制大小
$degree =30deg //控制片数 360/30=12
$pieceWidth = $pieceHeight/2
$linearwidth = $pieceWidth/2 //度数变更需要调整线性变化使得截取长度固定
$lineardegree = 90+$degree
$piece = 360/$degree
$pointHeight = 50px
$pointWidth = 20px
body
font-family:'Microsoft YaHei';
margin: 0
padding: 0
overflow hidden //旋转的容器过长,防止因旋转产生滑块
#viewport
margin 0 auto
width 300px
height: 300px
transform-origin: left
left:($pieceWidth)
position relative
for i in (1..$piece)
div:nth-child({i})
transform: rotate(($degree)*i)
transform-origin: left
if (i%2==0)
background-image: linear-gradient(($lineardegree),red $linearwidth, transparent $linearwidth);
else
background-image: linear-gradient(($lineardegree),grey $linearwidth, transparent $linearwidth);
.slice
width $pieceWidth
height $pieceHeight
border-radius: 0 $pieceWidth $pieceWidth 0
position absolute
left 0
top 0
span
display: inline-block
margin-top:12px
transform:rotate(13deg)//调整文字旋转
margin-left:8px
color #fff
background transparent
.pwrap
margin 0 auto
width ($pointWidth*2)
height $pointHeight
#point
width:0
height 0
position absolute
border-width: $pointWidth
border-top-width: $pointHeight
border-style: solid
transform translateY(($pointHeight/2))
border-color: black transparent transparent transparent
z-index 1
.start
display: flex
justify-content: center
margin-top: 10px
span
float left //不支持flex使用此兼容
font-size: 20px
padding: 5px
background brown
border-radius: 5px
color: white
box-shadow: black 0 0 10px 2px
cursor pointer
JS部分
- 这里一共有12片,我们思路就可以随机0到11,这样可以直接知道中奖的是哪个,然后多转几个360度就可以。所以这里我们需要旋转的度数等于初始的第一个元素位置的度数+中奖度数*每片所占度数+每片所占度数的一半(让指针停在中间)。
- 核心逻辑就是这个,另外抽完了需要重置transform和transition,不然下次就已经转了这么多圈。
import './main.styl'
let bouns = ['一等奖','二等奖','三等奖','四等奖','五等奖','六等奖',
'纪念奖','参与奖','没有奖','特别奖','六等奖','五等奖']
let fragment = document.createDocumentFragment()
bouns.forEach((item,index)=>{
let piece = document.createElement('div')
piece.className='slice slice-'+index
piece.innerHTML='<span>'+item+'</span>'
fragment.appendChild(piece)
})
document.querySelector('#viewport').appendChild(fragment)
let degree = 30
let initdegree = 720
let time = 16*1000
let isclick = true
document.querySelector('.start > span').onclick=function(e){
if(isclick){
let n = randomArr(0,(360/degree)-1)
let totaldegree = -(degree*(n+1)+initdegree+degree*0.5 )
isclick =false
let div = document.querySelector('#viewport')
div.style.transform='rotate('+totaldegree+'deg)'
div.style.transition='transform 16s cubic-bezier(0,.47,.31,1.03)'
setTimeout(() => {
alert('抽中了'+bouns[n]+'!');
isclick=true
div.style.transform='rotate('+ 0 +'deg)'
div.style.transition='none'
}, time);
}
}
function randomArr (start,end){
return Math.round(start+Math.random()*(end-start))
}