三分钟带你实现一个跨平台抽奖程序

333 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

canvas

Canvas API 提供了一个通过JavaScript 和 HTML<canvas>元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。Canvas API 主要聚焦于 2D 图形。而同样使用<canvas>元素的 WebGL API 则用于绘制硬件加速的 2D 和 3D 图形。

<canvas> 最早由 Apple 引入 WebKit,用于 Mac OS X 的 Dashboard,随后被各个浏览器实现。如今,所有主流的浏览器都支持它。

通过canvas,我们几乎可以实现任意我们能想到的形状的绘制。今天我们就借助canvas去实现一个抽奖的功能。

lucky-canvas实践

image.png

这里借助lucky-canvas插件快速实现。该插件中奖品 / 文字 / 图片 / 颜色 / 按钮均可自由配置;支持同步 / 异步抽奖;中奖概率前 / 后端可控;支持 JS / TS / JQ / Vue / React / 微信小程序 / UniApp / Taro 等;并且多端使用 / 表现形式完全一致;自动根据设备 dpr 调整清晰度;并支持使用 百分比 / rem / rpx 属性来适配移动端布局

实现转盘抽奖demo

image.png

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #my-lucky {
        margin: 0 auto;
      }
    </style>
  </head>

  <body>
    <div id="my-lucky"></div>
    <script src="https://unpkg.com/lucky-canvas@1.7.24"></script>

    <script>
      const myLucky = new LuckyCanvas.LuckyWheel("#my-lucky", {
        width: "240px",
        height: "240px",
        blocks: [
          { padding: "20px" },
          {
            padding: "20px",
            imgs: [
              {
                src: "./background5.png",
                width: "100%",
                rotate: true,
              },
            ],
          },
        ],
        prizes: [
          {
            range: 10,
            fonts: [
              {
                text: "ipad",
                fontSize: "10px",
              },
            ],
          },
          {
            range: 10,
            fonts: [
              {
                text: "罗技键鼠一套",
                fontSize: "10px",
              },
            ],
          },
          {
            range: 10,
            fonts: [
              {
                text: "小米显示器",
                fontSize: "10px",
              },
            ],
          },
          {
            range: 10,
            fonts: [
              {
                text: "空气净化器",
                fontSize: "10px",
              },
            ],
          },
          {
            range: 10,
            fonts: [
              {
                text: "iPhone13",
                fontSize: "10px",
              },
            ],
          },
          {
            range: 10,
            fonts: [
              {
                text: "小米扫地机器人",
                fontSize: "10px",
              },
            ],
          },
          {
            range: 10,
            fonts: [
              {
                text: "防蓝光眼镜",
                fontSize: "10px",
              },
            ],
          },
          {
            range: 10,
            fonts: [
              {
                text: "switch一台",
                fontSize: "10px",
              },
            ],
          },
        ],
        defaultConfig: {
          speed: 15,
        },
        buttons: [
          {
            radius: "45%",
            imgs: [
              {
                src: "./zhizhen.png",
                width: "120%",
                top: "-144%",
              },
            ],
          },
        ],
        start: function () {
          // 开始游戏
          myLucky.play();
          // 使用定时器模拟接口
          setTimeout(() => {
            // 结束游戏
            myLucky.stop();
          }, 3000);
        },
      });
      // 开始
      // myLucky.play()
    </script>
  </body>
</html>

实现九宫格抽奖demo

image.png

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #my-lucky {
        margin: 0 auto;
      }
    </style>
  </head>

  <body>
    <div id="my-lucky"></div>
    <script src="https://unpkg.com/lucky-canvas@1.7.24"></script>
    <script>
      const prizeImg = [
        {
          src: "./emoji (1).png",
          width: "50%",
          top: "25%",
        },
        {
          src: "./emoji (2).png",
          width: "50%",
          top: "25%",
        },
        {
          src: "./emoji (3).png",
          width: "50%",
          top: "25%",
        },
        {
          src: "./emoji (4).png",
          width: "50%",
          top: "25%",
        },
      ];
      const myLucky = new LuckyCanvas.LuckyGrid("#my-lucky", {
        width: "200px",
        height: "200px",
        blocks: [
          { padding: "10px", background: "#869cfa" },
          { padding: "10px", background: "#e9e8fe" },
        ],
        prizes: [
          { x: 0, y: 0, imgs: [prizeImg[0]] },
          { x: 1, y: 0, imgs: [prizeImg[1]] },
          { x: 2, y: 0, imgs: [prizeImg[2]] },
          { x: 2, y: 1, imgs: [prizeImg[3]] },
          { x: 2, y: 2, imgs: [prizeImg[0]] },
          { x: 1, y: 2, imgs: [prizeImg[1]] },
          { x: 0, y: 2, imgs: [prizeImg[2]] },
          { x: 0, y: 1, imgs: [prizeImg[3]] },
        ],
        defaultStyle: {
          background: "#b8c5f2",
        },

        buttons: [
          {
            x: 1,
            y: 1,
            background: "rgba(0,0,0,0)",
            imgs: [
              {
                src: "./play.png",
                width: "100%",
                height: "100%",
              },
            ],
          },
        ],
        start: function () {
          // 开始游戏
          myLucky.play();
          // 使用定时器模拟接口
          setTimeout(() => {
            // 结束游戏
            myLucky.stop();
          }, 3000);
        },
      });
    </script>
  </body>
</html>

实现老虎机抽奖demo

image.png

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #my-lucky {
        margin: 0 auto;
      }
    </style>
  </head>

  <body>
    <div id="my-lucky"></div>
    <script src="https://unpkg.com/lucky-canvas@1.7.24"></script>
    <script>
      const myLucky = new LuckyCanvas.SlotMachine("#my-lucky", {
        width: "240px",
        height: "180px",
        // 背景配置
        blocks: [
          { padding: "10px", background: "#869cfa" },
          { padding: "10px", background: "#e9e8fe" },
        ],
        //折这插槽转速、方向
        slots: [
          { speed: 5, direction: 1 },
          { speed: 5, direction: -1 },
          { speed: 5, direction: 1 },
        ],
        // 奖品
        prizes: [
          {
            background: "#bac5ee",
            borderRadius: "10px",
            imgs: [
              {
                width: "60%",
                top: "20%",
                src: "./emoji (1).png",
              },
            ],
          },
          {
            background: "#bac5ee",
            borderRadius: "10px",
            imgs: [
              {
                width: "60%",
                top: "20%",
                src: "./emoji (2).png",
              },
            ],
          },
          {
            background: "#bac5ee",
            borderRadius: "10px",
            imgs: [
              {
                width: "60%",
                top: "20%",
                src: "./emoji (3).png",
              },
            ],
          },
          {
            background: "#bac5ee",
            borderRadius: "10px",
            imgs: [
              {
                width: "60%",
                top: "20%",
                src: "./emoji (4).png",
              },
            ],
          },
        ],
        defaultConfig: {
          rowSpacing: "10px", //行间距
          colSpacing: "10px",
        },
      });

      // 开始游戏
      const playGame = () => {
        myLucky.play();
        setTimeout(() => {
          // 假设 4 种结果
          const res = [
            [9, 9, 6],
            [0, 0, 7],
            [6, 9, 1],
            [8, 2, 8],
          ];
          // 随机取一组数据
          const index = res[(Math.random() * 4) >> 0];
          // 调用 stop 方法停止游戏
          myLucky.stop(index);
        }, 500);
      };
      // 循环演示
      playGame();
      // setInterval(() => {
      //     playGame()
      // }, 6000)
    </script>
  </body>
</html>

lucky-canvas采用monorepo方式管理packages

项目使用lerna实现多包管理,主包为core目录,副包为各平台特性包,例如:react、taro、uni、vue、微信小程序包。

这里放一张monorepo和传统mutalrepo区别。 image.png

结语

该插件可配置参数还很多,可以根据你的需求实现很多我们常见的抽奖场景,官网提供了不少简单的案例,但是复杂需求就要靠自己一步步配置参数实现了。 注:示例中代码均可以在github中查看,可直接运行。