美文网首页
H5 Canvas抽奖大转盘代码实现及总结

H5 Canvas抽奖大转盘代码实现及总结

作者: 辣瓜瓜 | 来源:发表于2018-09-14 23:30 被阅读0次

    最近项目上写了一个签到页面,放在h5、ios和安卓中一起用 ,其中有一个功能是抽奖大转盘,这是一个很常用的功能,现在总结记录一下:

    效果gif

    需求

    1、每种奖品的中奖概率由后台确定,非随机。
    2、页面上大转盘中的奖品图品和名称有后台提供,灵活非静态。

    技术栈

    1、HTML5 Canvas
    2、引用Jquery插件jQueryRotate.js

    踩坑和注意

    1、绘制后的画布文字模糊,画布设置尺寸后,css将其设置为一半大小,如此就相当于画了一张200*400的图片,然后设置他显示成100*200的大小,这样一来就变得清晰了。需要注意的是,这样将画布放大之后,绘制的过程中对应的那些坐标,长度等等都要相应的放大

    <canvas width="200" height="400" style="width: 100px;height: 200px;"></canvas>
    

    2、canvas加载奖品图片,全都堆叠在左上角,原因是绘制画布时图片还没加载出来,需要使用onload解决

    //注意需要等图片加载完成后绘制
    window.onload = function() {
        drawWheelCanvas();
    };
    

    3、ios的Webview ajax不兼容,因为当时是本地作为服务器测试的,部署在服务器上就行了。参考

    4、save()与restore()区别</br>
    save表示保存save函数之前的状态;</br>restore表示获取save保存的状态

    5、canvas是从水平位置开始绘制的


    6、实现转盘四周闪烁效果,其实就是两张图片的切换,如图


    两张图片的切换
    四周闪烁效果.gif

    具体代码

    第一步:HTML布局
    <div class="wheel">
        <canvas class="item" id="wheelCanvas" width="422px" height="422px"></canvas>
        <img class="pointer" src="images/wheel-pointer.png"/><!--大转盘指针图片-->
    </div>
    
    
    第二部:绘制大转盘

    做一些画布的基础设置,此处预先假设抽奖奖项为6项

    //获取canvas画布
    var canvas = document.getElementById("wheelCanvas");
    var ctx = canvas.getContext("2d");
    var canvasW = canvas.width; // 画板的高度
    var canvasH = canvas.height; // 画板的宽度
    //计算每个奖项所占角度数
    var baseAngle = Math.PI * 2 / 6;
    ctx.clearRect(0,0,canvasW,canvasH);//去掉背景默认的黑色
    console.log(canvasW);
    ctx.strokeStyle = "#199301"; //设置画图线的颜色
    ctx.font = '26px Microsoft YaHei';//设置字号字体
    

    循环绘制6个60度的扇形,canvas是从水平位置开始绘制的,效果如图

    colors = ["#AE3EFF","#4D3FFF","#FC262C","#3A8BFF","#EE7602","#FE339F"];
    for(var index = 0; index < 6; index++) {
        var angle = index * baseAngle;       
        ctx.fillStyle = colors[index];//设置每个扇形区域的颜色
        ctx.beginPath();//开始绘制
        ctx.arc(canvasW * 0.5, canvasH * 0.5, 170, angle, angle + baseAngle, false);
        ctx.arc(canvasW * 0.5, canvasH * 0.5, 68, angle + baseAngle, angle, true);
        //context.arc(x,y,r,sAngle,eAngle,counterclockwise);创建弧/曲线
        ctx.stroke();//开始链线
        ctx.fill();//填充颜色
        ctx.save();//保存当前环境的状态
    }
    

    循环绘制6个60度的扇形,并放上文字图片

    colors = ["#AE3EFF","#4D3FFF","#FC262C","#3A8BFF","#EE7602","#FE339F"];
    rewardUrl =[]//从服务器请求回来的imgurl
    prizeId =[]//从服务器请求回来的奖项
    // 图片信息
    var imgUrl1 = new Image();
    imgUrl1.src = turnWheel.rewardUrl[0];
    var imgUrl2 = new Image();
    imgUrl2.src = turnWheel.rewardUrl[1];
    var imgUrl3 = new Image();
    imgUrl3.src = turnWheel.rewardUrl[2];
    var imgUrl4 = new Image();
    imgUrl4.src = turnWheel.rewardUrl[3];
    var imgUrl5 = new Image();
    imgUrl5.src = turnWheel.rewardUrl[4];
    var imgUrl6 = new Image();
    imgUrl6.src = turnWheel.rewardUrl[5];
    //注意需要等图片加载完成后绘制
    window.onload = function() {
        drawWheelCanvas();
    };
    
    for(var index = 0; index < 6; index++) {
        var angle = index * baseAngle;       
        ctx.fillStyle = colors[index];//设置每个扇形区域的颜色
        ctx.beginPath();//开始绘制
        ctx.arc(canvasW * 0.5, canvasH * 0.5, 170, angle, angle + baseAngle, false);
        ctx.arc(canvasW * 0.5, canvasH * 0.5, 68, angle + baseAngle, angle, true);
        //context.arc(x,y,r,sAngle,eAngle,counterclockwise);创建弧/曲线
        ctx.stroke();//开始链线
        ctx.fill();//填充颜色
        ctx.save();//保存当前环境的状态
        ctx.fillStyle = "#fff000";
        var rewardName = prizeId[index];
        var line_height = 24;
        // translate方法重新映射画布上的 (0,0) 位置
        var translateX = canvasW * 0.5 + Math.cos(angle + baseAngle / 2) * turnWheel.textRadius;
        var translateY = canvasH * 0.5 + Math.sin(angle + baseAngle / 2) * turnWheel.textRadius;
        ctx.translate(translateX, translateY);
        // rotate方法旋转当前的绘图,因为文字适合当前扇形中心线垂直的!
        // angle,当前扇形自身旋转的角度 +  baseAngle / 2 中心线多旋转的角度  + 垂直的角度90°
        ctx.rotate(angle + baseAngle / 2 + Math.PI / 2);
        //设置文本位置,居中显示 
        ctx.fillText(rewardName, -ctx.measureText(rewardName).width / 2, 100);
        //添加对应图标
        if(index == 0){
            ctx.drawImage(imgUrl1,-35,0,60,60);
        }else if(index == 1){
            ctx.drawImage(imgUrl2,-35,0,60,60);
        }else if(index == 2){
            ctx.drawImage(imgUrl3,-35,0,60,60);
        }else if(index == 3){
            ctx.drawImage(imgUrl4,-35,0,60,60);
        }else if(index == 4){
            ctx.drawImage(imgUrl5,-35,0,60,60);
        }else{
            ctx.drawImage(imgUrl6,-35,0,60,60);
        }
        ctx.restore(); //很关键,还原画板的状态到上一个save()状态之前
    }
    
    
    第三部:设置旋转转盘配置
    //旋转转盘 item:奖品序号,从0开始的; txt:提示语 ,count 奖品的总数量;
    var rotateFunc = function(item, tip, count) {
        // 应该旋转的角度,旋转插件角度参数是角度制。
        var baseAngle = 360 / count;
        // 旋转角度 == 270°(当前第一个角度和指针位置的偏移量) - 奖品的位置 * 每块所占的角度 - 每块所占的角度的一半(指针指向区域的中间)
        angles = 360 * 3 / 4 - (item * baseAngle) - baseAngle / 2; // 因为第一个奖品是从0°开始的,即水平向右方向
        $('#wheelCanvas').stopRotate();
        // 注意,jqueryrotate 插件传递的角度不是弧度制。
        // 哪个标签调用方法,旋转哪个控件
        $('#wheelCanvas').rotate({
            angle: 0,
            animateTo: angles + 360 * 5, // 这里多旋转了5圈,圈数越多,转的越快
            duration: 8000,
            callback: function() { // 回调
                //弹出中奖提示
                turnWheel.bRotate = !turnWheel.bRotate;
            }
        });
    };
    
    第四部:点击抽奖事件

    此处需要做的是,在用户点击时向后台发送请求,接收中奖信息,开始旋转...

    // 抽取按钮按钮点击触发事件
    $('.pointer').click(function() {
        // 正在转动,直接返回
        if(turnWheel.bRotate) return;
    
        turnWheel.bRotate = !turnWheel.bRotate;
        var count = turnWheel.rewardNames.length;
    
        $.ajax({
            type: "POST",
            url: "./drawPrize.htm",
            data: {
                customerId: $(".customerId").val()
            },
            async: false,
            dataType: "json", // 返回数据类型
            success: function(data) {
                console.log(data);
                if(data.type == 1) { //积分不足
                    
                } else if(data.type == 2) { //抽奖次数已经用完
                
                } else { //抽奖次数已经用完
                    turnWheel.prizeId.forEach(function(currentValue, index) {
                        if(currentValue == data.prize.id) {
                            var item = index;
                            $(".award-warp .content").html(data.prize.name);
                            // 开始抽奖
                            rotateFunc(item, turnWheel.rewardNames[item], count);
                        }
                    })
                }
            },
            error: function(data) {
    
                console.log("网络错误,请检查您的网络设置!");
            }
        });
    
    });
    
    文章借鉴参考:http://www.cnblogs.com/bingwei/p/4830932.html
    完整代码:https://github.com/MiuMiu-S/Draw-a-iottery

    相关文章

      网友评论

          本文标题:H5 Canvas抽奖大转盘代码实现及总结

          本文链接:https://www.haomeiwen.com/subject/dwjmbftx.html