canvas实现大转盘

1,431 阅读1分钟

demo地址

源码地址

显示效果

canvas就是一张空白画布,然后你就可以用笔随意挥墨,所以一切能用css实现的效果都可以用canvas实现

思路

画布大小选择

canvas可以想像成img标签,自身有style,也有属性width、height,显示的大小有style决定。由于canvas是位图,放大会模糊,在高清屏(Retina),多个像素渲染一个点,所有设置canvas属性的width大于style中的width

<style>
.turntable{
  width: 300px;
  height: 300px;
}
</style>
<canvas id="turntable" width="800" height="800" class="turntable"></canvas>

环圆

ctx.save(); 
ctx.beginPath();
ctx.strokeStyle = '#a3d2e4';
ctx.lineWidth = 40;
ctx.arc(0, 0, 370, 0, 2 * Math.PI);
ctx.stroke();
ctx.restore();

环上点

ctx.save();
ctx.fillStyle = '#fff';
for (var i = 0; i < pointerCount; i++) {
  const x = 370 * Math.sin(2 * Math.PI * i / pointerCount)
  const y = 370 * Math.cos(2 * Math.PI * i / pointerCount)
  ctx.beginPath();
  ctx.arc(x, y, 10, 0, 2 * Math.PI)
  ctx.closePath();
  ctx.fill();
}
ctx.restore();

内环

ctx.save();
for (i = 0; i < count; i++) {
  ctx.fillStyle = i % 2 === 0 ? '#c1ecff' : '#def4ff'
  ctx.beginPath()
  ctx.moveTo(0, 0)
  ctx.arc(0, 0, 350, 2 * Math.PI / count * i, 2 * Math.PI / count * (i + 1))
  ctx.closePath()
  ctx.fill()
}
ctx.restore();

内环奖品文字

文字是多个文字,不重新渲染的话,文字会在一行显示

一等奖 为例子,要比 在显示在环的边缘

ctx.save();
ctx.rotate(2 * Math.PI / count / 2)
for (i = 0; i < count; i++) {
  ctx.fillStyle = '#80b4ce'
  ctx.textAlign = 'center'
  ctx.font = '42px Arial'
  ctx.beginPath()
  ctx.moveTo(0, 0)
  for (j = 0, len = blockTexts[i].length; j < len; j++) {
    ctx.fillText(blockTexts[i][j], 0, (180 / len) * j - 240)
  }
  ctx.rotate(2 * Math.PI / count)
  ctx.closePath()
}
ctx.restore();

点击按钮转动

借助于css的rotate

btn.onclick = go
// 转4圈,最后找到对应的奖项
const deg = 360 * 4 + Math.random() * 6 * (360 / 6)
function go() {
  canvas.style.transform = "rotate(" + deg + "deg)";
  canvas.style.transition = "all 5s";
}