要实现的功能
- 分割扇形
- 图片文字居中
- 图片最大尺寸限制
- 动画 缓动
步骤
config → init → loadingImg → drawImg → rotate
1. 配置基本参数
config: {
num: 6, // 奖品数量
width: 750, // canvas宽
height: 750, // canvas高
maxw: 140, // 中奖图片的最大宽
maxh: 100 // 中奖图片的最大高
}
2. 初始化
- 请求服务端获取奖品列表获取奖品数组
get gitfs = [...] ...
- 获取初始值
this.num = this.gifts.length
this.ctx = this.canvas.getContext('2d')
this.canvas.width = this.config.width
this.canvas.height = this.config.height
3. 加载图片
loadingImg () {
const x = this.config.width / 2
const y = this.config.height / 2
const r = this.config.height / 2
if (360 % this.num !== 0) {
alert('请配置正确奖项数量!')
}
Object.keys(this.gifts).forEach(index => {
let img = new Image()
img.onload = () => {
// 开始画图了
this.drawImg(x, y, r, this.num, this.ctx, index, img)
}
img.src = this.gifts[index].image
})
}
4. 画图
drawImg (x, y, r, num, ctx, index, img) {
ctx.save()
ctx.beginPath()
ctx.translate(x, y)
ctx.moveTo(0, 0)
// 计算每个扇形旋转的角度
ctx.rotate(index * (2 * Math.PI - 2 * Math.PI / num))
// 绘制扇形
ctx.arc(0, 0, r, 3 * Math.PI / 2 - Math.PI / num, 3 * Math.PI / 2 + Math.PI / num, false)
// 交叉色渲染
index % 2 === 0 ? ctx.fillStyle = '#339cf7' : ctx.fillStyle = '#4da9ff'
ctx.fill()
// 绘制边框
ctx.lineWidth = 0.5
ctx.strokeStyle = '#4da9ff'
ctx.stroke()
// 绘制奖品图片
// 目标尺寸
let _tw = img.width
let _th = img.height
if (img.width > this.config.maxw || img.height > this.config.maxh) {
if (img.width / img.height > this.config.maxw / this.config.maxh) {
// 更宽,按照宽度限定尺寸
_tw = this.config.maxw
_th = Math.round(this.config.maxw * (img.height / img.width))
} else {
_th = this.config.maxh
_tw = Math.round(this.config.maxh * (img.width / img.height))
}
}
ctx.drawImage(img, -_tw / 2, -y + 40, _tw, _th)
// 绘制文字
ctx.fillStyle = '#fff'
ctx.font = '32px bold'
ctx.textAlign = 'center'
ctx.fillText(this.gifts[index].name, 0, -y + 170)
ctx.restore()
this.css(this.container, 360 / num / 2)
this.css(this.pick, -360 / num / 2)
}
5. 旋转抽奖
- 抽奖事件触发
this.pick.addEventListener('click', () => {
ajax.... // 获取抽奖结果
this.rotate(deg) // 转盘转到指定位置
})
- 旋转角度计算
rotate (deg) {
// 取个30°以内的随机角度偏转
this.css(this.canvas, 3600 + deg - 360 / this.num / 2 + Math.floor(Math.random() * 30) * (Math.random() > 0.5 ? 1 : -1))
},
css (ele, deg) {
ele.style.transform = `rotate(${deg}deg)`
ele.style.webkitTransform = `rotate(${deg}deg)`
}
- 通过css加上缓动
transition:all 5s ease-in-out