使用Canvas绘制转盘

转盘绘制过程详解

转盘的绘制是通过 HTML5 Canvas API 来实现的,主要包含以下几个部分:

1. 初始化画布

javascript 复制代码
const canvas = canvasRef.value;
if (!canvas) return;

const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = Math.min(centerX, centerY) - 10;

ctx.clearRect(0, 0, canvas.width, canvas.height);

这部分代码:

  • 获取 canvas 元素的引用
  • 获取 2D 绘图上下文 ctx
  • 计算画布的中心点 centerXcenterY
  • 计算转盘的半径 radius(取画布宽高中较小值的一半,再减去 10 像素的边距)
  • 清空整个画布,准备绘制新的内容

2. 绘制旋转的扇形区域

javascript 复制代码
// 保存当前状态
ctx.save();

// 旋转整个画布
ctx.translate(centerX, centerY);
ctx.rotate((rotationAngle.value * Math.PI) / 180);
ctx.translate(-centerX, -centerY);

// 绘制每个扇形
prizeAngles.value.forEach((prize) => {
  const startAngle = (prize.startAngle * Math.PI) / 180;
  const endAngle = (prize.endAngle * Math.PI) / 180;
  
  ctx.beginPath();
  ctx.moveTo(centerX, centerY);
  ctx.arc(centerX, centerY, radius, startAngle, endAngle);
  ctx.closePath();
  
  ctx.fillStyle = prize.color;
  ctx.fill();
  
  // 绘制奖品名称
  ctx.save();
  ctx.translate(centerX, centerY);
  const textAngle = startAngle + (endAngle - startAngle) / 2;
  ctx.rotate(textAngle);
  ctx.textAlign = 'right';
  ctx.fillStyle = '#fff';
  ctx.font = 'bold 14px Arial';
  ctx.fillText(prize.name, radius - 20, 5);
  ctx.restore();
});

// 恢复状态
ctx.restore();

这部分代码实现了转盘的旋转和扇形区域的绘制:

  1. 旋转处理:

    • ctx.save() 保存当前绘图状态,以便后续恢复
    • 通过 translaterotate 方法实现整个转盘的旋转效果
    • 先将坐标系原点移到画布中心,旋转指定角度,再将原点移回原位置
  2. 绘制扇形:

    • 遍历每个奖品,根据其起始角度和结束角度绘制扇形
    • ctx.beginPath() 开始一个新的路径
    • ctx.moveTo(centerX, centerY) 将绘图点移到圆心
    • ctx.arc() 绘制圆弧,从起始角度到结束角度
    • ctx.closePath() 闭合路径,形成扇形
    • 使用奖品的颜色填充扇形
  3. 绘制奖品名称:

    • 再次保存绘图状态
    • 将坐标系原点移到圆心
    • 计算文本角度(扇形的中间位置)
    • 旋转坐标系,使文本沿着扇形的半径方向排列
    • 设置文本对齐方式、颜色和字体
    • 绘制文本,位置在距离边缘 20 像素处
    • 恢复绘图状态
  4. 恢复初始状态:

    • ctx.restore() 恢复到最初保存的状态,取消旋转效果

注意事项

  • save()restore() 必须成对使用,否则可能导致状态栈混乱。
  • 可以多次调用 save(),每次调用会将当前状态压入栈顶,restore() 则从栈顶弹出最近的状态(先进后出)。

3. 绘制指针(倒三角形)

javascript 复制代码
// 绘制倒三角形指针
ctx.beginPath();
// 指针底部中心点
const pointerBaseY = centerY - radius - 15;
// 绘制倒三角形
ctx.moveTo(centerX, pointerBaseY + 25); // 指针尖端,指向转盘
ctx.lineTo(centerX - 15, pointerBaseY); // 左上角
ctx.lineTo(centerX + 15, pointerBaseY); // 右上角
ctx.closePath();

// 填充和描边
ctx.fillStyle = 'red';
ctx.fill();
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.stroke();

这部分代码绘制了一个指向转盘的倒三角形指针:

  1. 定义指针底部中心点的位置,位于转盘上方
  2. 绘制倒三角形的三个点:
    • 尖端点:指向转盘
    • 左上角点:位于底部左侧
    • 右上角点:位于底部右侧
  3. 使用红色填充三角形
  4. 添加黑色边框,使指针更加明显

4. 绘制中心圆

javascript 复制代码
// 绘制中心圆
ctx.beginPath();
ctx.arc(centerX, centerY, 20, 0, Math.PI * 2);
ctx.fillStyle = '#fff';
ctx.fill();
ctx.strokeStyle = '#333';
ctx.lineWidth = 2;
ctx.stroke();

这部分代码在转盘中心绘制了一个白色圆形,带有深灰色边框:

  1. 在画布中心绘制一个完整的圆(从 0 到 2π)
  2. 半径为 20 像素
  3. 使用白色填充
  4. 添加深灰色边框,线宽为 2 像素

动画实现

转盘的旋转动画是通过 animateWheel 函数实现的,它使用 requestAnimationFrame 在每一帧更新 rotationAngle,然后重新绘制转盘,从而产生旋转效果。

js 复制代码
// 旋转转盘的动画
const animateWheel = () => {
  // 每帧旋转的角度
  rotationAngle.value += 10;
  
  // 保持角度在0-360之间
  if (rotationAngle.value >= 360) {
    rotationAngle.value -= 360;
  }
  
  drawWheel();
    
  if (props.isSpinning) {
    animationFrameId = requestAnimationFrame(animateWheel);
  }
};

大功告成:

相关推荐
ScriptBIN3 小时前
Javaweb--Vue
前端·vue.js
前端Hardy3 小时前
Vue 高效开发技巧合集:10 个实用技巧让代码简洁 50%+,面试直接加分!
前端·javascript·vue.js
ᖰ・◡・ᖳ3 小时前
JavaScript:神奇的ES6之旅
前端·javascript·学习·es6
前端Hardy3 小时前
HTML&CSS:一眼心动的 SVG 时钟
前端·javascript·css
又是忙碌的一天4 小时前
前端学习 JavaScript
前端·javascript·学习
右子6 小时前
微信小程序开发“闭坑”指南
前端·javascript·微信小程序
AGG_Chan6 小时前
flutter专栏--深入了解widget原理
开发语言·javascript·flutter
冰镇生鲜6 小时前
前端模拟 流式文本接口 打字机效果 mockStreamText
javascript
入秋6 小时前
Three.js后期处理实战:噪点 景深 以及色彩调整
前端·javascript·three.js