不依赖任何库:实现推广转盘三连中

一个乱写的推广转盘,很乱但是效果还行

 

 

<!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>
        * {
            margin: 0;
            padding: 0;
        }

        html,
        body {
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        .container {
            width: 100%;
            height: 100%;
            overflow-x: hidden;
            overflow-y: scroll;
        }

        .canvas-wrapper {
            position: relative;
        }

        .button {
            background: transparent;
            outline: none;
            border: none;
            display: block;
            position: absolute;
            left: 0;
            right: 0;
            top: 56vh;
            border-radius: 50%;
            margin: 0 auto;
            width: 100px;
            height: 100px;
        }

        #canvas {
            display: block;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="canvas-wrapper">
            <button class="button"></button>
            <canvas id="canvas"></canvas>
        </div>
        <div>信息</div>
    </div>
</body>
<script>
    // 获取像素比 高清cavas
    function getPixelRatio(context) {

        var backingStore = context.backingStorePixelRatio ||

            context.webkitBackingStorePixelRatio ||

            context.mozBackingStorePixelRatio ||

            context.msBackingStorePixelRatio ||

            context.oBackingStorePixelRatio ||

            context.backingStorePixelRatio || 1;

        return (window.devicePixelRatio || 1) / backingStore;

    };
    var wheel = new Wheel();

    // 公共类
    function Wheel() {
        let cav = document.getElementById('canvas');
        this.pointerRange = [];
        this.pointerIndex = 0;
        this.turned = []; //已经转中的下标数组
        this.turnTargetRotate = []; //要转的目的数组
        this.turnedCount = 0; // 转盘次数
        this.startTurn = false; // 开始抽
        this.delay = 20;
        this.speed = 1; //转速
        this.ctx = cav.getContext('2d');
        this.ratio = getPixelRatio(this.ctx);
        this.w = window.innerWidth;
        this.h = window.innerHeight;
        cav.style.width = this.w + 'px';
        cav.style.height = this.h + 'px';
        cav.width = this.w * this.ratio;
        cav.height = this.h * this.ratio;
    }
    Wheel.prototype.updatePointerIndex = function (rotate) {
        let rotateV = rotate % 360;
        let index = this.pointerRange.findIndex(d => rotateV < d);
        this.pointerIndex = index == -1 ? 0 : index;
    }

    // 转盘类
    function AwardRound({
        cx,
        cy,
        cr = 100,
        data = []
    }) {
        let angleStore = 0;
        let sum = 0;
        this.cx = cx * wheel.ratio;
        this.cy = cy * wheel.ratio;
        this.cr = cr * wheel.ratio;
        this.count = data.length;
        this.data = data.map((d, i) => {
            sum += d.angle;
            let prevData = data[i - 1];
            angleStore += d.angle + (i - 1 > 0 ? prevData.angle : 0);
            let startAngle = - 90 - (d.angle / 2);
            d.beginAngle = startAngle / 180 * Math.PI;
            d.endAngle = (startAngle + d.angle) / 180 * Math.PI;
            if (i == 0) {
                d.rotateAngle = 0;

            } else {
                d.rotateAngle = angleStore;
            }
            wheel.pointerRange.push(sum - (data[0].angle / 2));
            if (d.isTurn) {
                let prevItem = wheel.pointerRange[i - 1];
                wheel.turnTargetRotate.push({
                    rotate: ((wheel.pointerRange[i] - prevItem) / 2 + prevItem) + 3 * 360,
                    index: i
                })
            }

            return d;
        });
    }
    AwardRound.prototype.render = function () {
        let iconW = 36 * wheel.ratio;
        this.data.forEach((d, i) => {

            wheel.ctx.save();
            wheel.ctx.translate(this.cx, this.cy);
            wheel.ctx.rotate((d.rotateAngle) * Math.PI / 360);
            wheel.ctx.beginPath();

            // 画底盘
            wheel.ctx.fillStyle = d.background || '#fdf1e7';
            wheel.ctx.arc(0, 0, this.cr, d.beginAngle, d.endAngle);
            wheel.ctx.lineTo(0, 0);
            wheel.ctx.fill()
            // 名字
            wheel.ctx.fillStyle = d.color || '#000';
            wheel.ctx.font = `${d.fontSize ? d.fontSize * wheel.ratio : 16}px 微软雅黑`;
            wheel.ctx.textAlign = 'center';
            wheel.ctx.fillText(d.name || '', 0, - this.cr + 20 * wheel.ratio);

            // 图片
            if (d.icon) {
                wheel.ctx.drawImage(d.icon, -iconW / 2, -this.cr + 40 * wheel.ratio, iconW, iconW);
            }
            // 浮层
            wheel.ctx.fillStyle = '#000';
            wheel.ctx.globalAlpha = i == wheel.pointerIndex || wheel.turned.includes(i) ? 0 : 0.5;
            wheel.ctx.arc(0, 0, this.cr, d.beginAngle, d.endAngle);
            wheel.ctx.lineTo(0, 0);
            wheel.ctx.fill();

            wheel.ctx.restore();
        })

    }

    // 按钮类
    function Button({
        cx,
        cy
    }) {
        this.cx = cx * wheel.ratio;
        this.cy = cy * wheel.ratio;
        this.rotate = 0;
    }
    Button.prototype.render = function () {
        let tmpW = 25 * wheel.ratio;
        wheel.ctx.save()
        wheel.ctx.translate(this.cx, this.cy);
        wheel.ctx.rotate(this.rotate * Math.PI / 180);
        wheel.ctx.beginPath()
        wheel.ctx.fillStyle = '#FF910B';
        wheel.ctx.arc(0, 0, 50 * wheel.ratio, 0, Math.PI * 2);
        wheel.ctx.fill();
        wheel.ctx.moveTo(0, 0);
        wheel.ctx.lineTo(tmpW, 0);
        wheel.ctx.lineTo(0, -80 * wheel.ratio);
        wheel.ctx.lineTo(-tmpW, 0);
        wheel.ctx.fill();
        wheel.ctx.restore();
    }
    Button.prototype.update = function () {
        this.rotate += wheel.speed;
        if (wheel.startTurn) { // 开始转了
            if (this.rotate >= wheel.turnTargetRotate[wheel.turnedCount].rotate) { // 达到阈值
                wheel.delay--; //延时器
                if (wheel.delay > 0) {
                    // 休息一下
                    this.rotate = wheel.turnTargetRotate[wheel.turnedCount].rotate; // 保持抽到位置
                    wheel.speed = 0; //停止转动
                } else {
                    // 转下一次
                    wheel.turnedCount++; // 中次+1
                    wheel.turned.push(wheel.turnTargetRotate[wheel.turnedCount - 1].index);
                    wheel.speed = 20;
                    wheel.delay = 20;
                    if (wheel.turnedCount < 3) {
                        this.rotate = 0;
                    }
                }
            }
        }
        wheel.updatePointerIndex(this.rotate);
    }

    // 背景类
    function Background() {
        let img = new Image()
        img.src = './bg.png';
        this.bgImg = img;
    }
    Background.prototype.render = function () {
        let iconW = (wheel.w - 10) * wheel.ratio;
        let iconH = iconW * (846 / 720);
        wheel.ctx.drawImage(this.bgImg, 5 * wheel.ratio, wheel.h * wheel.ratio - iconH, iconW, iconH)
    }


    var awardData = [
        {
            icon: 'http://mdhw.oss-cn-hangzhou.aliyuncs.com/goods/1652065297220_maYiZc27.jpg',
            name: '感谢参与',
            background: '#fdf1e7',
            color: '#C24603',
            fontSize: '13',
            angle: 45,
        },
        {
            icon: '',
            name: 'AirJordan1',
            background: '#FFB876',
            color: '#C24603',
            fontSize: '11',
            angle: 25
        },
        {
            icon: 'http://mdhw.oss-cn-hangzhou.aliyuncs.com/goods/1652065313260_JDMZ2GTW.jpg',
            name: 'iPhone手机',
            background: '#BD1600',
            color: '#FEE28A',
            fontSize: '11',
            angle: 25,
            isTurn: true,
        },
        {
            icon: '',
            name: '蓝牙音箱',
            background: '#FFDAB2',
            color: '#C24603',
            fontSize: '11',
            angle: 25
        },

        {
            icon: 'http://mdhw.oss-cn-hangzhou.aliyuncs.com/goods/1652065297220_maYiZc27.jpg',
            name: '感谢参与',
            background: '#fdf1e7',
            color: '#C24603',
            fontSize: '13',
            angle: 45,
        },
        {
            icon: '',
            name: 'AirJordan1',
            background: '#FFB876',
            color: '#C24603',
            fontSize: '11',
            angle: 25
        },
        {
            icon: 'http://mdhw.oss-cn-hangzhou.aliyuncs.com/goods/1652065313260_JDMZ2GTW.jpg',
            name: 'iPhone手机',
            background: '#BD1600',
            color: '#FEE28A',
            fontSize: '11',
            angle: 25,
            isTurn: true,
        },
        {
            icon: '',
            name: '蓝牙音箱',
            background: '#FFDAB2',
            color: '#C24603',
            fontSize: '11',
            angle: 25
        },

        {
            icon: 'http://mdhw.oss-cn-hangzhou.aliyuncs.com/goods/1652065297220_maYiZc27.jpg',
            name: '感谢参与',
            background: '#fdf1e7',
            color: '#C24603',
            fontSize: '13',
            angle: 45,
        },
        {
            icon: '',
            name: 'AirJordan1',
            background: '#FFB876',
            color: '#C24603',
            fontSize: '11',
            angle: 25
        },
        {
            icon: 'http://mdhw.oss-cn-hangzhou.aliyuncs.com/goods/1652065313260_JDMZ2GTW.jpg',
            name: 'iPhone手机',
            background: '#BD1600',
            color: '#FEE28A',
            fontSize: '11',
            angle: 25,
            isTurn: true,
        },
        {
            icon: '',
            name: '蓝牙音箱',
            background: '#FFDAB2',
            color: '#C24603',
            fontSize: '11',
            angle: 25
        },
    ];
    awardData = awardData.map(d => {
        if (d.icon) {
            let img = new Image();
            img.src = d.icon;
            d.icon = img
        }
        return d
    })

    window.onload = function () {
        let iconH = (wheel.w - 10) * (846 / 720);
        let cx = wheel.w / 2;
        let cr = cx - 30;
        let cy = wheel.h - iconH + cr + 25;
        var btnDom = document.querySelector('.button')
        var background = new Background();
        var awardRound = new AwardRound({
            cx: cx,
            cy: cy,
            cr: cr,
            data: awardData
        });
        var button = new Button({
            cx,
            cy,
        });
        const clickDown = function () {
            if (wheel.startTurn) {
                btnDom.removeEventListener('click', clickDown);
                return;
            }
            button.rotate = 0;
            wheel.startTurn = true;
            wheel.speed = 20;
        }
        btnDom.addEventListener('click', clickDown)

        function doAnimate() {
            // 清除画布
            wheel.ctx.clearRect(0, 0, 10000, 10000)
            // 渲染转盘背景
            background.render();
            // 渲染转盘
            awardRound.render();
            // 渲染按钮
            button.update();
            button.render();
            if (wheel.turnedCount < 3) {
                requestAnimationFrame(() => {
                    doAnimate();
                })
            }
        }
        doAnimate();

    }

</script>

</html>

 

posted @ 2022-06-23 09:44  豆浆不要油条  阅读(14)  评论(0编辑  收藏  举报