2201_75340854 2023-05-19 18:03 采纳率: 31.8%
浏览 96
已结题

用html整个会动的大转盘

用以下知识,整个指针会动,有灯光交替闪烁,能实现页面刷新初始化的大转盘

img

img

img

img

img

img

img

  • 写回答

2条回答 默认 最新

  • 啊泮 2023-05-19 18:16
    关注

    可以参考:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
        <title>大转盘抽奖</title>
    <style>
    *{
        margin: 0;
        padding: 0;
    }
    
    #lottery-wrap{
        position: relative;
        display: block;
        margin: 150px auto;
        width: 300px;
        border: 8px solid #eac34c;
        border-radius: 50%;
        box-shadow: 3px 0 3px #fffdc9, 0px 3px 3px #fffdc9, -3px 0 3px #fffdc9, 0px -3px 3px #fffdc9;
    }
    canvas{
        display: block;
    }
    
    #lottery-handler{
        position: absolute;
        z-index: 2;
        width: 60px;
        height: 74px;
        left: 50%;
        top: 50%;
        margin: -44px 0 0 -30px;
        background: url(./images/handler.png) no-repeat 50%;
        background-size: contain;
    }
    </style>
    </head>
    <body style="background-color: darkkhaki;">
    
    <div id="lottery-wrap">
        <div id="lottery-handler"></div>
        <canvas width="300" height="300" id="lottery"></canvas>
    </div>
    
    <script src="./Lottery.js"></script>
    <script>
    
    /*模拟ajax请求数据返回*/
    function _ajax(callback){
        /*jQuery.ajax({
            url: url,
            data: data,
            success: function(response){
                callback && callback(response);
            }
        })*/
        setTimeout(function(){
            var _index   = Math.floor(Math.random()*4);//此处是概率,可自己写算法定义概率
            var response = {id: 1, name: products[_index].name, index: _index};
            callback && callback(response);
        }, 100);
    }
    //此处是定义的奖项
    var products = [
        {
            "imgUrl": "./images/redpacket.png",
            "name": "10元红包"
        },
        {
            "imgUrl": "./images/redpacket.png",
            "name": "20元红包"
        },
        {
            "imgUrl": "./images/redpacket.png",
            "name": "50元红包"
        },
        {
            "imgUrl": "./images/redpacket.png",
            "name": "100元红包"
        }
    ];
    
    new Lottery(document.getElementById('lottery'), {
        handler: document.getElementById('lottery-handler'),
        handlerCallback: function(_interface){
            /*ajax获取中奖结果*/
            _ajax(function(response){
                console.log(response);
                /*指定停止的位置:索引*/
                _interface.stop(response.index, function(){
                    alert('恭喜你中得:' + response.name)
                });
            });
        },
        images: {
            width: 22,
            height: 29,
            y: '88%',
        },
        products: products
    });
    
    </script>
    </body>
    </html>
    
    (function(){
    /**
    
     * 
     * [Lottery 大转盘抽奖js插件, 无依赖, 简单易用]
     * @param  {[Dom Object]} oCanvas [canvas对象]
     * @param  {[Object]}     options [配置参数, 请参考底部的_setOptions方法中的config对象]
     */
    function Lottery(){
        return this._init.apply(this, arguments);
    }
    Lottery.prototype = {
        _init: function(oCanvas, options){
            if(!oCanvas)return false;
            this.oCanvas  = oCanvas;
            this.options  = this._setOptions(options);
            this.size     = (this.options.products || []).length;
            this.angle    = 2 * Math.PI / this.size;
            this.sAngle   = 1.5*Math.PI - this.angle/2;
            this.ctx      = oCanvas.getContext("2d");
    
            this.rotate   = 0;
            /*存储图片元素*/
            this.oImages  = [];
            /*存储图片链接*/
            this.imgUrl   = [];
            this.isOver   = true;
    
            this._setLayout();
            this._fixOptions();
    
            this._draw();
            this._start();
        },
        /*修正options参数*/
        _fixOptions: function(){
            this.outerRadius   = parseInt(this.options.outerRadius) || this.radius;
            this.innerRadius   = parseInt(this.options.innerRadius) * this.options.scale || 0;
            this.options.speed = Math.min(Math.max(1, this.options.speed), 30);
    
            if(String(this.options.font.y).indexOf('%') > 0){
                this.options.font.y = this.outerRadius * parseInt(this.options.font.y)/100;
            }
            
            if(String(this.options.images.y).indexOf('%') > 0){
                this.options.images.y = this.outerRadius * parseInt(this.options.images.y)/100;
            }
        },
        /*重置canvas尺寸*/
        _setLayout: function(){
            var oCanvas  = this.oCanvas;
            var diameter = oCanvas.offsetWidth || oCanvas.clientWidth || oCanvas.width;
    
            oCanvas.style.height = diameter + 'px';
            oCanvas.style.width = diameter + 'px';
    
            diameter = diameter * this.options.scale;
    
            this.diameter = oCanvas.width = oCanvas.height = diameter;
            this.radius   = diameter/2;
        },
        /*获取文字的样式*/
        _getFontStyle: function(){
            var scale = this.options.scale;
            var fontStyle = this.options.font;
            return '{{style}} {{weight}} {{size}}/{{lineHeight}} {{family}}'.replace(/\{\{([^}]*)\}\}/g, function(a, b){
                return b == 'size' ? parseInt(fontStyle[b]) * scale + 'px' : fontStyle[b];
            })
        },
        /*画扇形*/
        _drawArc: function(){
            this.ctx.save();
            var fillStyle = this.options.fillStyle;
            if(!fillStyle)return;
          
            for(var i = 0; i < this.size; i++){
                var sAngle = this.sAngle + this.angle*i;
                this.ctx.beginPath();
                this.ctx.fillStyle = fillStyle[i%fillStyle.length];
                this.ctx.arc(this.radius, this.radius, this.innerRadius, sAngle, sAngle + this.angle, false);
                this.ctx.arc(this.radius, this.radius, this.outerRadius, sAngle + this.angle, sAngle, true);
                this.ctx.closePath();
                this.ctx.fill();
            }
            this.ctx.restore();
        },
        isArray: function(arr){
            return arr && Object.prototype.toString.call(arr) == '[object Array]';
        },
        /*画扇形上的文字*/
        _drawText: function(){
            var fonts = this.options.font;
            var scale = this.options.scale;
            for(var i = 0; i < this.size; i++){
                var textArr  = this._cleverBreak(this.options.products[i].name);
                this.ctx.save();
                this.ctx.translate(this.radius, this.radius);
                this.ctx.rotate(this.angle * i);
                this.ctx.fillStyle = this.isArray(fonts.color) ? fonts.color[i%fonts.color.length] : fonts.color;
                this.ctx.font = this._getFontStyle();
                this.ctx.fillText(textArr[0], -this.ctx.measureText(textArr[0]).width/2, - fonts.y);
    
                if(textArr[1]){
                    var y = -(fonts.y-(parseInt(fonts.size)*scale*this.options.font.lineHeight));
                    this.ctx.fillText(textArr[1], -this.ctx.measureText(textArr[1]).width/2, y);
                }
                this.ctx.restore();
    
                this.options.products[i].imgUrl && this.imgUrl.push(this.options.products[i].imgUrl);
            }
        },
        /*文字断行*/
        _cleverBreak: function(str){
            var res, keys = this.options.breakText;
            if(!str){return res}
            for(var i = 0; i < keys.length; i++){
                var idx = str.indexOf(keys[i]);
                if(idx > -1){
                    res = [str.substr(0, idx), str.substr(idx)];
                    break;
                }
            }
            return res || [str];
        },
        /*绘制图片*/
        _drawImg: function(){
            var self   = this, 
                width  = this.options.images.width,
                height = this.options.images.height;
    
            this._loadImg(this.imgUrl, function(img){
                var scale = self.options.scale;
                for(var i = 0; i < img.length; i++){
                    var ret = img[i], 
                        w   = (width || ret.width) *  scale,
                        h   = (height || ret.height) * scale;
    
                    self.ctx.save();
                    self.ctx.translate(self.radius, self.radius);
                    self.ctx.rotate(self.angle * i);
                    self.ctx.drawImage(ret, -w/2 , -self.options.images.y, w, h);
                    self.ctx.restore();
                };
            });
        },
        /*绘制画布*/
        _draw: function(){
            var options  = this.options,
                products = options.products,
                cx = this.cx, imgArr = [];
    
            this.ctx.clearRect(0, 0, this.diameter, this.diameter);
            this._drawArc();
            this._drawText();
            this._drawImg();
        },
        /*加载要绘制的图片*/
        _loadImg: function(srcArr, callback){
            var img  = document.createElement('img');
            var cur  = cur || 0;
            var self = this;
    
            if(!self.cur){
                self.cur = 0;
                self.oImages = [];
            }
    
            var src = srcArr[self.cur++];
            img.src = src + '?' + self.cur;
    
            img.onload = function(){
                self.oImages.push(this);
                if(self.cur < srcArr.length){
                    self._loadImg(srcArr, callback);
                }else{
                    self.cur = false;
                    callback(self.oImages);
                }
                this.onload = false;
            };
    
            img.onerror = function(){
                //console.log(this.src);
            }
        },
        /*开始旋转转盘*/
        _beginRotate: function(){
            var self = this, cSpeed = 0, is = 0,
                iSpeed = this.options.speed;
    
            self.cSpeed = 0;
            self.isOver = false;
            clearInterval(self.timer);
    
            self.timer = setInterval(function(){
                is = (iSpeed-cSpeed)/iSpeed;
                is = is > 0 ? Math.ceil(is) : Math.floor(is);
                cSpeed += is;
                if(cSpeed>iSpeed){
                    is = iSpeed;
                }
                self.cSpeed = cSpeed;
                self.rotate += cSpeed;
                self.setRotateStyle(self.rotate);
            }, 30);
        },
        /*开始抽奖*/
        _start: function(){
            var self = this;
            if(!this.options.handler)return;
            this._fastClick(this.options.handler, function(ev){
                if(self.hasClass(this, 'disabled'))return;
                if(self.isOver){
                    self.sTime = self.now();
                    self._beginRotate();
                    typeof self.options.handlerCallback === 'function' && self.options.handlerCallback.call(this, self);
                }
            });
        },
        _off: function(elemet, eventType, callback){
            elemet.removeEventListener(eventType, callback, false);
        },
        _fastClick: function(elemet, callback){
            if('ontouchstart' in document){
                elemet.addEventListener('touchstart', callback, false);
            }else{
                elemet.addEventListener('click', callback, false);
            }
        },
        /*简单的继承*/
        extend: function(source, distance){
            for(var attr in distance){
                if(distance[attr] !== undefined){
                    source[attr] = distance[attr];
                }
            }
            return source;
        },
        /*设置旋转*/
        setRotateStyle: function(rotate){
            this.prefix('transform', 'rotate(' + rotate + 'deg)');
        },
        prefix: function(attr, val){
            if(!val)return;
            var _fix = ['moz', 'o', 'webkit'], self = this;
            _fix.map(function(item){
                self.oCanvas.style[item + self.capitalize(attr)] = val;
            });
            self.oCanvas.style[attr] = val;
        },
        capitalize: function(str){
            return str.substr(0, 1).toUpperCase() + str.substr(1);
        },
        /*判断指定className是否存在*/
        hasClass: function(elemet, className){
            var cls = elemet.className;
            return !!cls.match(new RegExp('\\b' + className + '\\b'));
        },
        /*停止转动, idx为指定停止的位置*/
        stop: function(idx, callback){
            var iTime = Math.max(0, this.options.duration - this.now() + this.sTime);
            var self  = this, durTimer = null;
            durTimer = setTimeout(function(){
                if(self.options.interval > 0){
                    self._stop(idx, function(_interface){
                        _interface.isOver = false;
                        _interface.intervalTimer = setTimeout(function(){
                            _interface.isOver = true;
                            clearTimeout(_interface.intervalTimer);
                            callback && callback(_interface);
                        }, _interface.options.interval)
                    });
                }else{
                    self._stop.apply(self, arguments);
                }
                clearTimeout(durTimer);
            }, iTime);
    
        },
        _stop: function(idx, callback){
            var stopTimer = null, self = this, iAngle = 360/self.size;
            var iTarget   = self.rotate + 360*4 + (self.size - idx - self.rotate%360/iAngle) * iAngle;
            var iSpeed    = this.options.speed;
    
            this.timer && clearInterval(this.timer);
            function move(){
                var cSpeed = (iTarget - self.rotate)/iSpeed;
                    cSpeed = cSpeed > 0 ? Math.ceil(cSpeed) : Math.floor(cSpeed);
    
                if(cSpeed > self.cSpeed){
                    cSpeed = self.cSpeed;
                }
                self.rotate += cSpeed;
                self.rotate >= iTarget && (self.rotate = iTarget, self.isOver = true);
                self.setRotateStyle(self.rotate);
                if(self.isOver){clearInterval(stopTimer); callback && callback(self);}
            }
            stopTimer = setInterval(move, 30);
        },
        now: function(){
            return new Date() - 0;
        },
        ua: {
            isIos: /iphone|ipad/i.test(navigator.userAgent),
            isAndroid: /android/i.test(navigator.userAgent)
        },
        /*设置配置项*/
        _setOptions: function(options){
            /*默认配置项*/
            var config = {
                /*点击抽奖元素*/
                handler: '',
                /*点击抽奖的回调*/
                handlerCallback: function(_interface){},
                outerRadius: '',
                innerRadius: 0,
                /*循环填充数组颜色*/
                fillStyle: ['#ffdf8a', '#fffdc9'],
                /*重复触发的间距时间*/
                interval: 1000,
                /*速度越大越快*/
                speed: 12,
                /*运动最少持续时间*/
                duration: 3000,
                /*字体位置与样式*/
                /*画布显示缩放比例,值为1 安卓模糊*/
                scale: this.ua.isIos ? 2 : 2,
                /*字体样式,浅拷贝 需整个font对象传入*/
                font: {
                    y: '50%',
                    color: '#ee6500',
                    /*循环填充字体颜色*/
                    //color: ['#f00', '#ee6500'],
                    style: 'normal',
                    weight: 500,
                    size: '10px',
                    lineHeight: 1,
                    family: 'Arail'
                },
                /*图片位置与尺寸*/
                images: {
                    y: '88%',
                    width: 32,
                    height: 32
                },
                /*打断文字换行*/
                breakText: ['金币', '红包'],
                /*礼物*/
                products: [
                    /*{
                        imgUrl: 'http://',
                        text: '苹果手机',
                    }*/
                ]
            };
            return this.extend(config, options);
        }
    };
    
    window.Lottery = Lottery;
    }());
    
    
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月20日
  • 赞助了问题酬金15元 5月19日
  • 创建了问题 5月19日

悬赏问题

  • ¥15 AD9164瞬时带宽1.8G,怎么计算出来?
  • ¥20 为什么安装CSiBridge时出现了这个问题,尝试了很多方法都不行,求详细操作步骤?
  • ¥15 鼠标右键,撤销删除 复制 移动,要怎样删除
  • ¥15 使用MATLAB进行余弦相似度计算加速
  • ¥15 服务器安装php5.6版本
  • ¥15 我想用51单片机和数码管做一个从0开始的计数表 我写了一串代码 但是放到单片机里面数码管只闪烁一下然后熄灭
  • ¥20 系统工程中,状态空间模型中状态方程的应用。请猛男来完整讲一下下面所有问题
  • ¥15 我想在WPF的Model Code中获取ViewModel Code中的一个参数
  • ¥15 arcgis处理土地利用道路 建筑 林地分类
  • ¥20 使用visual studio 工具用C++语音,调用openslsx库读取excel文件的sheet问题