Canvas打造三重玩法转盘:绘制转盘(1)

目录

前言

效果图展示

一、 转盘的三重玩法

二、svg绘制转盘指针

三、Canvas绘制转盘

 效果图展示

 四、Canvas扩展

五、完整代码

 效果图展示


前言

想象一下,你正置身于一个充满惊喜与刺激的世界,手中的转盘仿佛掌握着无尽的财富与好运。而今天,我们将为你揭秘如何用Canvas打造三种不同玩法的转盘,让你在每一次旋转中都能感受到不同的乐趣与期待!

效果图展示 1a88950a5e1149f985e886d9f7194031.png

一、 转盘的三重玩法

    1、玩法一:等分转盘

首先,我们来看看等分转盘。这种转盘的特点是每个区域都均等划分,每个区域的面积、形状都完全相同。无论是红色区域、蓝色区域还是绿色区域,它们都有着相同的概率被选中。当你轻轻一点,转盘飞速旋转,最终停留在哪个区域,完全取决于你的运气。这种等分转盘,简单直接,公平公正,是初学者们的最爱。

    2、玩法二:不等分转盘

然而,如果你觉得等分转盘太过单调,那么不等分转盘或许能满足你的需求。在这种玩法中,每个区域的面积、形状都不尽相同。有些区域占据了大半个转盘,而有些区域则只有小小的一角。这样的设计,让每个区域被选中的概率也各不相同。旋转转盘时,你或许会期待那些大面积的区域能够停下来,但也可能被那些小巧玲珑的区域所惊艳。不等分转盘,充满了未知与惊喜,让你在每一次旋转中都能体验到不同的刺激感。

    3、玩法三:等分转盘与概率不相等

除了区域大小的不同,我们还可以在等分上进行调整。有些转盘虽然区域相等,但每个区域被选中的概率却是不相等的。这是通过复杂的算法和计算实现的,让转盘在旋转时能够自动调整速度和角度,确保每个区域被选中的机会不完全相等。而另一些转盘则直接让概率与区域大小挂钩,大区域有着更高的被选中概率。这样的转盘,既考验玩家的运气,也考验设计者的智慧。

二、svg绘制转盘指针

  1. 通过iconfont官网下载svg指针代码:iconfont官网链接
<svg t="1713059543990" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
            p-id="1835" width="200" height="200">
            <path
                d="M263.577601 776.630449a242.559588 242.559588 0 0 1 138.417007-218.124973L483.818959 23.36268a27.485506
                 27.485506 0 0 1 54.283873 0l81.824351 535.142796a242.559588 242.559588 0 0 1 138.417006 218.124973
                  247.369551 247.369551 0 0 1-494.739102 0z"
                p-id="1836" fill="#f4ad13"></path>
</svg>

三、Canvas绘制转盘

  1.  html、css部分内容

#css

<style>
        .box {
            width: 100%;
            height: 550px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            position: relative;
        }

        canvas {
            display: block;
            margin: 20px auto;
        }

        svg {
            position: absolute;
            left: 50%;
            top: 50%;
            width: 70px;
            height: 70px;
            margin-left: -35px;
            margin-top: -65px;
        }
    </style>

#html

<div class="box">
        <canvas id="rouletteCanvas" width="302" height="302"></canvas>
        <svg t="1713059543990" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
            p-id="1835" width="200" height="200">
            <path
                d="M263.577601 776.630449a242.559588 242.559588 0 0 1 138.417007-218.124973L483.818959 23.36268a27.485506
                 27.485506 0 0 1 54.283873 0l81.824351 535.142796a242.559588 242.559588 0 0 1 138.417006 218.124973
                  247.369551 247.369551 0 0 1-494.739102 0z"
                p-id="1836" fill="#f4ad13"></path>
        </svg>
        <button onclick="startSpinning()">开始抽奖</button>
    </div>

 2、JavaScript实现

     ①、获取canvas的dom并通过getContext 方法用于获取canvas 元素上的渲染上下文

const canvas = document.getElementById('rouletteCanvas');

 const ctx = canvas.getContext('2d');

     ②、转盘参数所用到的参数

对于转盘的前期准备工作,首先我们需要考虑到需要的转盘参数,参数内容分别有: 奖项数量、 每个奖项的角度、转盘半径、转盘中心X坐标  、转盘中心Y坐标  、中奖内容、和每个奖项的背景颜色。

// 转盘参数  
const numSegments = 8; // 奖项数量  
const anglePerSegment = Math.PI * 2 / numSegments; // 每个奖项的角度  Math.PI=π
const radius = 150; // 转盘半径  
const centerX = canvas.width / 2; // 转盘中心X坐标  
const centerY = canvas.height / 2; // 转盘中心Y坐标  
const prizeText = ['奖品1', '奖品2', '奖品3', '奖品4', '奖品5', '奖品6', '奖品7', '奖品8'];// 各奖项内容
const prizeColors = ['#ff0000', '#8e44ad', '#0000ff', '#32cd32', '#f0f', '#ff5733', '#90ee90', '#888888']; // 各奖项背景颜色

     ③、绘制转盘背景方法

// ctx.arc(centerX, centerY, radius, startAngle, endAngle, false);

// centerX 和 centerY:圆弧所在圆的圆心坐标。

// radius:圆弧所在圆的半径。

// startAngle 和 endAngle:圆弧的起始角度和结束角度,以弧度为单位。

// 这个参数表示绘制的是逆时针方向的圆弧。如果设置为true,则会绘制顺时针方向的圆弧。

function drawRoulette() {
        //清除整个 <canvas> 元素上的所有内容,将画布恢复到初始的空白状态。
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        for (let i = 0; i < numSegments; i++) {
            const startAngle = (i ) * anglePerSegment;//起始角度
            const endAngle = (i+1 ) * anglePerSegment;//结尾角度
            const x = centerX + Math.cos(startAngle) * radius;// 输出startAngle的余弦值
            const y = centerY + Math.sin(startAngle) * radius;// 输出startAngle的正弦值
            ctx.beginPath();
            // 开始绘制圆盘
            ctx.arc(centerX, centerY, radius, startAngle, endAngle, false);
            ctx.closePath();
            ctx.fillStyle = prizeColors[i];// 填充扇形区域
            ctx.fill(); 
            ctx.save();//保存当前的Canvas状态
            ctx.restore();
        }
    }

     ④、初始化转盘和指针的调用

// 初始化转盘和指针  
drawRoulette();

 效果图展示

81291506b82446eeb6bd25197e611724.png

 四、Canvas扩展

/*

arc()方法绘制的圆弧不会自动连接到圆心,因此如果你想要一个完整的扇形效果

(包括从圆弧到圆心的线段),你需要手动绘制这些线段。但是,对于填充操作,

你不需要手动闭合路径,因为fill()会自动处理这个问题。

*/

    1、每个奖项内容的填充 

// 绘制文本
const textAngle = startAngle + (endAngle - startAngle) / 2;
const textX = centerX + Math.cos(textAngle) * (radius - 40);//x轴上的坐标值,基于圆的半径和指定的角度Angle
const textY = centerY + Math.sin(textAngle) * (radius - 40);//y轴上的坐标值,基于圆的半径和指定的角度Angle

ctx.translate(textX, textY);// 将Canvas的原点移动到(textX, textY)位置
ctx.rotate(textAngle);// 旋转Canvas沿着指定的textAngle方向排列
ctx.textAlign = 'center';// 设置文本的对齐方式为居中
ctx.textBaseline = 'middle';// 设置文本垂直居中
ctx.fillStyle = '#fff';// 设置文本填充颜色为白色
ctx.fillText(prizeText[i], 0, 0);//指定位置绘制文本
ctx.rotate(textAngle),这个坐标是基于平移和旋转后的新坐标系。

     2、 绘制连接圆心的线段(可选,如果填充的话不需要,因为fill()会自动闭合路径)

ctx.lineTo(centerX, centerY);

    3、如果需要,也可以绘制扇形的边框

// 如果需要,也可以绘制扇形的边框
ctx.lineWidth = 1; // 设置边框宽度
ctx.strokeStyle = '#666'; // 设置边框颜色
ctx.stroke();

五、完整代码

本章为绘制转盘,完整代码供学习参考,扩展已详细进行注解。Canvas三重玩法请关注下一章。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>转盘抽奖</title>
    <style>
        .box {
            width: 100%;
            height: 550px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            position: relative;
        }

        canvas {
            display: block;
            margin: 20px auto;
        }

        svg {
            position: absolute;
            left: 50%;
            top: 50%;
            width: 70px;
            height: 70px;
            margin-left: -35px;
            margin-top: -65px;
        }
    </style>
</head>

<body>
    <div class="box">
        <canvas id="rouletteCanvas" width="302" height="302"></canvas>
        <svg t="1713059543990" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
            p-id="1835" width="200" height="200">
            <path
                d="M263.577601 776.630449a242.559588 242.559588 0 0 1 138.417007-218.124973L483.818959 23.36268a27.485506 27.485506 0 0 1 54.283873 0l81.824351 535.142796a242.559588 242.559588 0 0 1 138.417006 218.124973 247.369551 247.369551 0 0 1-494.739102 0z"
                p-id="1836" fill="#f4ad13"></path>
        </svg>
        <button onclick="startSpinning()">开始抽奖</button>
    </div>
    <script>
        const canvas = document.getElementById('rouletteCanvas');
        const ctx = canvas.getContext('2d');
        // 转盘参数  
        const numSegments = 8; // 奖项数量  
        const anglePerSegment = Math.PI * 2 / numSegments; // 每个奖项的角度  Math.PI=π
        const radius = 150; // 转盘半径  
        const centerX = canvas.width / 2; // 转盘中心X坐标  
        const centerY = canvas.height / 2; // 转盘中心Y坐标  
        const pointerLength = 50; // 指针长度  
        const prizeText = ['奖品1', '奖品2', '奖品3', '奖品4', '奖品5', '奖品6', '奖品7', '奖品8'];// 各奖项内容
        const prizeColors = ['#ff0000', '#8e44ad', '#0000ff', '#32cd32', '#f0f', '#ff5733', '#90ee90', '#888888']; // 各奖项背景颜色

        // 绘制转盘背景  
        function drawRoulette() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            for (let i = 0; i < numSegments; i++) {
                const startAngle = (i + 6) * anglePerSegment;
                const endAngle = (i + 7) * anglePerSegment;
                const x = centerX + Math.cos(startAngle) * radius;
                const y = centerY + Math.sin(startAngle) * radius;
                ctx.beginPath();
                ctx.arc(centerX, centerY, radius, startAngle, endAngle, false);
                ctx.lineTo(centerX, centerY);
                ctx.closePath();
                ctx.fillStyle = prizeColors[i];
                ctx.fill();
                ctx.lineWidth = 1;
                ctx.strokeStyle = '#666'; 
                ctx.stroke();
                const textAngle = startAngle + (endAngle - startAngle) / 2;
                const textX = centerX + Math.cos(textAngle) * (radius - 40);
                const textY = centerY + Math.sin(textAngle) * (radius - 40); 
                ctx.save();
                ctx.translate(textX, textY);
                ctx.rotate(textAngle);
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillStyle = '#fff';
                ctx.fillText(prizeText[i], 0, 0);
                ctx.restore();
            }
        }
        // 初始化转盘和指针  
        drawRoulette();
    </script>
</body>

</html>

 效果图展示

43713b0dd53a4e7dba20b8ba9ac42f22.png

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炑焽

蓝海新风口,高薪稳定不内卷

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值