转盘式抽奖的第一个问题是随机数个奖品在转盘上的定位,当然每个点的坐标是可以计算出来的:
不过在js中不需要这么繁琐,有n个奖品,一个圆360度,所以每个奖品之间的夹角是 360 / (n - 1)度,也就是说每个奖品相对中心旋转一定角度就可以了。
如果在canvas中那么可以自定义中心位置,如果用js的话,我目前为了演示采取的做法是每个点绝对定位在父元素顶部的中部(0, 50%),设置高度和父元素相同,这样变形原点就在父元素的(50%,50%)处了(不改动transform-origin的话)。
跑马灯式抽奖效果的实现要简单许多,因为原理就是将当前的高亮元素重置,并使下一个元素高亮,这样可以在setInerval()中根据高亮次数(每个元素高亮一次,次数加1)来调整间隔。转盘式抽奖的问题在于转盘减速到选中奖品这个过程中角度差异最大达到360度,所以抽奖间隔不是很好控制。所以最终我把减速这段效果给去除了。
我估计用canvas实现转盘式旋转抽奖的效果要容易很多,canvas可以定义原点,而且可以很方便的绘制扇形(2直线+1圆弧)。
给出的代码里各位不能自定义奖品的样式,因为li标签的样式是用来保证变形原点的,当然可以在li标签内加上一个span标签,在span标签内自定义奖品样式或者用图片,如果这样实现的话,那么推荐在操作DOM的时候使用innerHTML,类似innerHTML += 'xxx',然后一次性加到父元素的节点下,我这里给个演示图片:
下面给出代码,目前的抽奖效果不是很好,之后会想想换用animaion来实现。
<!doctype html> <html> <head> <meta charset="utf-8"> <title>lottery</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="format-detection" content="telephone=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <style> /*css reset*/ html{font-family:"Helvetica Neue",Helvetica,STHeiTi,sans-serif;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;} body{-webkit-overflow-scrolling:touch;margin:0;} ul{margin:0;padding:0;list-style:none;outline:none;} dl,dd{margin:0;} a{display:inline-block;margin:0;padding:0;text-decoration:none;background:transparent;outline:none;color:#000;} a:link,a:visited,a:hover,a:active{text-decoration:none;color:currentColor;} a,dt,dd{-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;} img{border:0;} p{margin:0;} input,button,select,textarea{margin:0;padding:0;border:0;outline:0;background-color:transparent;} /*css*/ body { height: 100vh; text-align: center; } .wrapper { margin: 0 auto; padding: 40px 0; max-width: 750px; } .wrapper .lottery { position: relative; display: inline-block; width: 600px; height: 600px; border: 1px solid #f0f0f0; border-radius: 50%; background-color: #f0f0f0; box-sizing: border-box; } .wrapper .lottery .list { position: absolute; top: 0; left: 300px; width: 0; height: 600px; } </style> </head> <body> <div class="wrapper"> <ul class="lottery"> </ul> </div> <script> var doc = document, fragment = doc.createDocumentFragment(), $ = function(node) { return doc.querySelector(node); }; var lotteryList = [0, 1, 2, 3, ,4], length = lotteryList.length, averRotate = 360 / (length - 1); lotteryList.forEach(function(i) { var node = doc.createElement('li'); node.setAttribute('id', 'list' + i); node.setAttribute('class', 'list'); node.innerHTML = i; fragment.appendChild(node); }) $('.lottery').appendChild(fragment); lotteryList.forEach(function(i) { $('#list' + i).style.transform = 'rotate(' + i * averRotate + 'deg)'; }) var speed = 40, i = 0, angle = 0, drawn = Math.floor(Math.random() * length); lotteryTimer = setInterval(lotterFunc, speed); function lotterFunc() { $('.lottery').style.transform = 'rotate(' + ++angle + 'deg)'; if (angle % 360 == 0) { i++; } if ((angle % 5 == 0) && speed > 10) { clearInterval(lotteryTimer); speed -= 1; lotteryTimer = setInterval(lotterFunc, speed); } else if (angle == (720 + drawn * averRotate)) { clearInterval(lotteryTimer); } } </script> </body> </html>
2017年7月2日补充:
尝试了一下用canvas绘制一个抽奖的转盘,canvas我只会基础:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>lottery</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="format-detection" content="telephone=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <style> /*css reset*/ html{font-family:"Helvetica Neue",Helvetica,STHeiTi,sans-serif;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;} body{-webkit-overflow-scrolling:touch;margin:0;} ul{margin:0;padding:0;list-style:none;outline:none;} dl,dd{margin:0;} a{display:inline-block;margin:0;padding:0;text-decoration:none;background:transparent;outline:none;color:#000;} a:link,a:visited,a:hover,a:active{text-decoration:none;color:currentColor;} a,dt,dd{-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;} img{border:0;} p{margin:0;} input,button,select,textarea{margin:0;padding:0;border:0;outline:0;background-color:transparent;} /*css*/ body { height: 100vh; text-align: center; } .wrapper { margin: 0 auto; padding: 40px 0; max-width: 750px; } </style> </head> <body> <div class="wrapper"> <canvas id="lottery" width="600" height="600"> 您的浏览器不支持canvas </canvas> </div> <script> var img = new Image(); img.src = '1.png'; var lotteryArr = [0, 1, 2, 3, 4, 5, 6]; var averRotate = 2 * Math.PI / (lotteryArr.length - 1); var lottery = document.getElementById('lottery'); var ctx = lottery.getContext('2d'); ctx.translate(300, 300); ctx.beginPath(); ctx.arc(0, 0, 280, 0, 2 * Math.PI); ctx.stroke(); ctx.closePath(); ctx.strokeStyle = 'rgba(0, 0, 0, .2)'; img.onload = function() { ctx.beginPath(); lotteryArr.forEach(function(data, i) { ctx.save(); ctx.rotate(averRotate * i); ctx.moveTo(0, 0); ctx.lineTo(0, - 280); ctx.stroke(); ctx.restore(); ctx.save(); ctx.rotate(averRotate * (i + 1 / 2)); ctx.drawImage(img, -25, 180, 50, 50); ctx.restore(); }) ctx.closePath(); } ctx.fillStyle = '#f50505'; ctx.strokeStyle = '#f50505'; ctx.beginPath(); ctx.arc(0, 0, 38, 0, 2 * Math.PI); ctx.stroke(); ctx.fill(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(-25, 0); ctx.lineTo(0, -80); ctx.lineTo(25, 0); ctx.stroke(); ctx.fill(); ctx.closePath(); </script> </body> </html>