小程序canvas大转盘

// luckRoll.wxml

    
    

需要定义的数据

// luckRoll.js
data: {
    trunBtn: false,//抽奖按钮是否可以点击
    itemsNum: 3, //大转盘等分数,可根据后台配置加载
    itemsArc: 0, //大转盘每等分角度
    coupons: [],//每个扇形中的文字填充
    isRotate: -180, // 初始旋转角度
}

创建一个canvas对象,因为它是个组件,所以在传入转盘数据的时候,初始化canvas

properties: {
    rollOptions: {
        type: Array,
        observer(val) {
            if(val.length > 0) {
                this.setData({
                    coupons: val,
                    itemsNum: val.length
                })
                const ctx = wx.createCanvasContext("canvas", this); //创建id为canvas的绘图
                this.getGiftList(ctx)
            }
        }
    }
},
getGiftList(ctx) {
    let that = this;
    let itemsArc = 360/that.data.itemsNum
    that.setData({
        itemsArc
    }, function () {
        const query = wx.createSelectorQuery().in(that)
        query.select('#canvas-bg').boundingClientRect()
        query.exec(function (rect) {
            w1 = parseInt(rect[0].width / 2);
            h1 = parseInt(rect[0].height / 2);
            that.drawRegion(itemsArc, ctx);//每一份扇形的内部绘制。
        })
    })
}

绘制扇形

drawRegion(e, ctx) {
    let that = this;
    let itemsArc = e;//每一份扇形的角度
    let num = that.data.itemsNum;//等分数量
    let itemArr = that.data.coupons.map(item=>item.name);//放文字的数组
    for (let i = 0; i < num; i++) {
        ctx.beginPath();
        ctx.moveTo(w1, h1);
        ctx.arc(w1, h1, w1 - 2, itemsArc * i * Math.PI / 180, (itemsArc + itemsArc * i) * Math.PI / 180);//绘制扇形,默认从第四象限开始画,所以区域编号1的地方为三点钟开始位置
        ctx.closePath();
        const colorList = ['#7cd8e3', '#ffffff']
        ctx.setFillStyle(colorList[i % 2]);
        ctx.fill();
        ctx.save();
        ctx.beginPath();
        ctx.translate(w1, h1);//将原点移至圆形圆心位置
        ctx.rotate((itemsArc * (i + 1 + (num - 2) * 0.25)) * Math.PI / 180);//旋转文字
        if (num >= 6) {
            ctx.setFontSize(18);//设置文字字号大小
        } else {
            ctx.setFontSize(20);//设置文字字号大小
        }
        if (i % 2 == 0) {
            ctx.setFillStyle("#ffffff");//设置文字颜色
        } else {
            ctx.setFillStyle("#7cd8e3");//设置文字颜色
        }
        ctx.setTextAlign("center");//使文字垂直居中显示
        ctx.setTextBaseline("middle");//使文字水平居中显示
        if (itemArr[i].length < 7) {
            ctx.setFontSize(12);//设置文字字号大小
            ctx.fillText(itemArr[i], 0, -(h1 * 0.75));
        } else if (itemArr[i].length >= 7 && itemArr[i].length <= 10) {
            let len = Math.ceil(itemArr[i].length / 2)
            ctx.fillText(itemArr[i].slice(0, len), 0, -(h1 * 0.80));
            ctx.fillText(itemArr[i].slice(len), 0, -(h1 * 0.65));
            ctx.setFontSize(20);//设置文字字号大小
        } else {
            let mainInfo = itemArr[i].slice(0, 10) + '...'
            ctx.fillText(mainInfo.slice(0, 6), 0, -(h1 * 0.80));
            ctx.fillText(mainInfo.slice(6, 13), 0, -(h1 * 0.65));
            ctx.setFontSize(20);//设置文字字号大小
        }
        ctx.restore();//保存绘图上下文,使上一个绘制的扇形保存住。
    }
    ctx.draw();
    setTimeout(()=>{
        wx.canvasToTempFilePath({
            x: 0,
            y: 0,
            width: 2 * w1,
            height: 2 * h1,
            destWidth: 8 * w1,
            destHeight: 8 * h1,
            fileType: 'jpg', 
            quality: 1,//图片的质量,目前仅对 jpg 有效。取值范围为 (0, 1],不在范围内时当作 1.0 处理。
            canvasId: 'canvas',
            success: function (res) {
                var tempFilePath = res.tempFilePath;
                that.setData({
                    tempFilePath: res.tempFilePath
                })

            },
            fail: function (res) {
                console.log('----------  ', res)
            }
        }, that)
    },1000)
    ctx.draw(true);//参数为true的时候,保存当前画布的内容,继续绘制
}
wx.canvasToTempFilePath 特别重要,必须将canvas转换为图片在页面上渲染,不然会出现各种问题,canvas用translateY移出页面显示

另外wx.canvasToTempFilePath必须写在setTimeout里面,不然安卓机的图片是黑屏

上面转盘已经画成,下面就要转动起来

startRoll(index) {
    let that = this;
    let turntableRegionId = index+1
    let rotate = that.data.isRotate - that.data.isRotate % 360 + (720 - Number(turntableRegionId - 1) * that.data.itemsArc - 0.5 * that.data.itemsArc - 90)
    // 转动过程写在css动画里面,时长3s
    that.setData({
        isRotate: rotate + 2160
    })
    let cur = that.data.coupons[index]
    let isBingo = !!cur.isPrize
    let award = cur.name
    that.setData({
        isBingo: isBingo, // 是否中奖
        award: award // 奖品
    })
    setTimeout(()=>{
        //3S后显示最终结果弹窗
        that.setData({
            dialogShow: true
        })
    },3000)
}

其他细节,项目不同再另外写
核心css

.canvas-container {
    width: 550rpx;
    height: 550rpx;
    transition:all 3s ease;
    position: absolute;
    top: 45rpx;
    left: 110rpx;
    z-index: 1;
    border-radius: 50%;
    overflow: hidden;
}
.canvas{
    width: 550rpx;
    height: 550rpx;
    display: block;
    position: fixed;
    left: -5000px;
}

你可能感兴趣的:(小程序)