资讯专栏INFORMATION COLUMN

React完美实现可配置转盘

isaced / 2940人阅读

摘要:最近在做一些活动的需求,发现用到转盘的机会很大。转盘的旋转控制首先,能够在点击转的按钮时候做一些判断是否可以开转,使用变量来控制。

最近在做一些h5活动的需求,发现用到转盘的机会很大。

代码已经开源,感兴趣的同学可查看react-turnplate

先上效果

额,因为gif压缩了,所以画质有点。。。呵呵,没关系的

需求

于是将转盘组件化,具体的需求是:

    传入一个奖品数组.

    能够在点击转的按钮时候做一些判断是否可以开转.

    开转后有一个回调,用于请求奖品返回.

    转动结束/中奖回调.

    转动按钮,背景图可配置. 具体props为

params type desc
image_spin string spin button
background_1 string background_1
background_2 string background_2
prizeList array [{icon:"imageurl",name:"prize1",id:1},{icon:"imageurl",name:"prize1",id:2}]
award object award should be null first,after request back return an object like prizelist[0]
canStartRotate bool control the turnplate should startRotate
onTryRotate func trigger after click the rotate button,should do some check stuff and if it"s ok,set canStartRotate to be true then the turnplate start rotating,meanwhile request for the award and after the request finish,set the award
rotateFinish func
实现思路

转盘外圈的闪烁

这里主要是两张背景图不断替换,通过定时器,不断替换background形成闪烁的效果.

//外面闪闪发光的东东 _outDiscFlash() { const { background_1, background_2 } = this.props; this.outShowImg1 = !this.outShowImg1; if (this.outShowImg1) { this.refs.turnplateBorder.style.backgroundImage = `url(${background_1})`; } else { this.refs.turnplateBorder.style.backgroundImage = `url(${background_2})`; } this._flashTimer = setTimeout(this._outDiscFlash, this.outDiskDiffTimer); } _initFlash() { const { background_1 } = this.props; this.outDiskDiffTimer = 100; this.outShowImg1 = true; this._flashTimer = null; this.refs.turnplateBorder.style.backgroundImage = `url(${background_1})`; }

转盘的奖品绘制

1.首先是根据传进来的奖品数组个数,用canvas来画扇形填充。用devicePixelRatio是为了适配手机。

draw() { const { prizeList } = this.props; let rotateDeg = 360 / prizeList.length / 2 + 90, // 扇形回转角度 ctx; const canvas = document.getElementById("canvas"); if (!canvas.getContext) { return; } // 获取绘图上下文 ctx = canvas.getContext("2d"); for (let i = 0; i < prizeList.length; i++) { // 保存当前状态 ctx.save(); // 开始一条新路径 ctx.beginPath(); // 位移到圆心,下面需要围绕圆心旋转 ctx.translate(105 * this.devicePixelRatio, 105 * this.devicePixelRatio); // 从(0, 0)坐标开始定义一条新的子路径 ctx.moveTo(0, 0); // 旋转弧度,需将角度转换为弧度,使用 degrees * Math.PI/180 公式进行计算。 ctx.rotate((((360 / prizeList.length) * i - rotateDeg) * Math.PI) / 180); // 绘制圆弧 ctx.arc( 0, 0, 105 * this.devicePixelRatio, 0, (2 * Math.PI) / prizeList.length, false ); // 颜色间隔 if (i % 2 == 0) { ctx.fillStyle = "#FFEAB0"; } else { ctx.fillStyle = "#ffffff"; } // 填充扇形 ctx.fill(); // 绘制边框 ctx.lineWidth = 0.5; ctx.strokeStyle = "#e4370e"; ctx.stroke(); // 恢复前一个状态 ctx.restore(); } }

2.其次是将产品填充,做一个rotate。

_getTurnPrizeList() { const { prizeList } = this.props; const turnplateList = []; for (let i = 0; i < prizeList.length; i++) { const turnplateItem = (
  • "turnplate-item" key={i}>
    ${i / prizeList.length}turn)` }}>
    {prizeList[i].name}
  • ); turnplateList.push(turnplateItem); } return
      "turnplate-list">{turnplateList}
    ; }

    转盘的旋转控制

    首先,能够在点击转的按钮时候做一些判断是否可以开转,使用变量canStartRotate来控制。当canStartRotate为true后,一直旋转,直到传进来的award不为空,每次transitionEnd判断award的状态,不为空就结束旋转,回调rotateFinish。

    UNSAFE_componentWillReceiveProps(nextProps, nextState) { if (this.props.prizeList.length != nextProps.prizeList.length) { this.draw(); } //如果在请求,还没返回结果,就先转着 if ( !this.props.canStartRotate && nextProps.canStartRotate && !nextProps.award ) { this._initFlash(); this._outDiscFlash(); this._justRotate(); } if (!this.props.award && nextProps.award) { this.setState({ award: nextProps.award }); } } _justRotate() { const container = document.getElementById("turnplate"); const rotateDeg = 360 * 3; this.setState({ lastRotateDeg: rotateDeg + this.state.lastRotateDeg, rotating: true, justRotate: true }); container.style.transform = "rotate(" + (rotateDeg + this.state.lastRotateDeg) + "deg)"; } finishRotate() { const { rotateFinish } = this.props; const { award, justRotate } = this.state; //如果奖品来了,并且不是justRotate if (award && !justRotate) { clearTimeout(this._flashTimer); this.setState({ rotating: false }); rotateFinish(award); } //如果奖品来了,是justRotate,就开始抽 else if (award && justRotate) { this._lottery(); } else { //否则就继续等吧兄弟 this._justRotate(); } }
    "turnplate-wrapper" id="turnplate" onTransitionEnd={this.finishRotate.bind(this)} >

    每次transition结束的时候都查看award是否已经传入,可看到finishRotate有3种情况的判断

    待实现的功能

      转盘大小可配置

      转盘每个扇形颜色可配置 ....

    这些之后都会在react-turnplate完善。

    此处只是提供了一种思路,抛砖引玉。

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/6744.html

    相关文章

    • 转盘抽奖脚本自己撸

      摘要:效果需求很多场景都需要做各种活动,抽奖最是司空见惯了,跑马灯的,转盘的,下面先花几分钟撸出一个转盘的吧,当然网上至少有一打的可供参考。但是我们只差一个定时器循环了接下里实现这个主循环,不断更新值就可以了。 demo 效果 需求 很多场景都需要做各种活动,抽奖最是司空见惯了,跑马灯的,转盘的,下面先花几分钟撸出一个转盘的吧,当然网上至少有一打的 demo 可供参考。真的只需要一点点时间而...

      赵春朋 评论0 收藏0
    • 基于 Nest.js(Node.js) 的模块化敏捷开发系统架构 Notadd 2.0 Beta2

      摘要:快速开始下载码云高速下载安装执行包安装,如无,请先执行自动创建数据库配置必须使用必须使用必须使用运行更新月报年月年月年月年月年月年月年月年月年月下载地址码云一点说明月将发布用户中心模块和模块,月月后续还会有商城模块微信模块 前言 大多数 node.js 框架都没解决架构问题,使得 node.js 没能像 spring 一样的适合大型项目开发和维护的框架。 nest.js 出现改变了这种...

      gaosboy 评论0 收藏0
    • canvas之转盘抽奖

      摘要:最近工作中重构了抽奖转盘,给大家提供一个开发转盘抽奖的思路需求转盘根据奖品数量不同而有变化目录结构由于业务需要所以开发了两个版本抽奖,和,不过部分只能替换图片,没有功能逻辑。 最近工作中重构了抽奖转盘,给大家提供一个开发转盘抽奖的思路 需求 1、转盘根据奖品数量不同而有变化 2、canvas 目录结构 showImg(https://segmentfault.com/img/bVbwL...

      _ang 评论0 收藏0
    • 300行代码写一个音乐播放器小程序

      摘要:项目主要是微信小程序也用到了等。前端部分主要是歌曲播放控制和交互部分的代码,更多关于小程序的内容可见微信小程序开发文档小程序框架结构微信小程序的入口是根目录下的它们分别描述的小程序的主题逻辑和公共配置部分。 刚进公司不久,因为公司部门年后业务拓展的关系,可能在年后会被分配到公司的微信公众号组做小程序相关的开发工作,因此写了个微信小程序wx-audio踩坑。目前还有一些功能没有写完:如返...

      chenatu 评论0 收藏0

    发表评论

    0条评论

    最新活动
    阅读需要支付1元查看
    <