写在前面,年会将至,需求自然也跟各种抽奖有关啦。最近刚好接了一个紧急的九宫格抽奖需求,顺便也记录一下撸这个简易九宫格的过程吧。

本文可能涉及以下内容:

  • 九宫格布局
  • 九宫格动效
  • 抽奖逻辑处理
  • 前后端联调

九宫格布局

九宫格大家应该都挺熟悉的吧,就是九个格子嘛,下面给大家看看我们线上的九宫格抽奖↓↓

等等..上面这个好像不是九个格子(它是DEMO)

这个布局相信大家都很熟悉吧,特别是看过阮一峰Flex 布局教程:实例篇的童鞋们,是不是倍感亲切。

没错,我们这个布局是基于flex完成的,主要思路是纵横元素的分离。

  • 整个九宫格区域应该是一个定宽高(其实不定也无所谓)的块元素,将每一行(row)纵向排列。
  • 每一行都是一个row,我们在row中将每个item块space-between或space-around(根据业务自行判断)。
  • 每个item里面的内容也用flex水平居中一下,然后该怎么还原设计稿就怎么还原吧。

遇坑点,其实也不算坑,算是一个移动端自适应上的问题吧。

这里涉及到了rem布局的问题,由于某些历史原因,我们的项目并没有使用rem的方法来进行移动端页面的开发.

这就导致我们在开发某些需要高自适应的组件时比较蛋疼。但是最近在写其他项目的时候想到一个挺适合我们使用的方案,不过对浏览器、手机系统的版本可能有些许要求。

@function pxWithVw($n){@return 100vw * $n / 375
}@function pxWithVwMax($n){@return 480px * $n / 375
}
@mixin pxVw2width($n) {width: pxWithVw($n);max-width: pxWithVwMax($n);
}
@mixin pxVw2height($n) {height: pxWithVw($n);max-height: pxWithVwMax($n);
}
复制代码

虽然我们没用rem布局,但是我们还是接了scss的,借用scss的mixin我们可以很爽的还原设计稿的各种参数,之所以还要限定一个Max值主要还是因为我们的项目支持在PC端查看,所以需要给它限定一个极限的宽度。

问题来了,pxVw2height里面为啥有个vw?其实就是个像素比例的问题,设计稿中宽度与设计稿中设备宽度的比例不就自然是每个px对应屏幕的比例了嘛。

不过这样写会有个不确定的地方,就是不同的DPR下,这种方法对像素还原是否有影响,关于这点我暂时无法确定,不过还是会抽空去试验一下的。

九宫格动效&抽奖逻辑处理

按理来说动效和抽奖逻辑是两码事,但是我们是在React里面开发的,我觉得有必要把它们放到一起讲。

动效核心

动效的触发核心是activedId的实时变更,通过定时器,在某一时间间隔内改变父组件state中的activedId,以达到九宫格中"蹬蹬蹬"的效果。

class RowItem extends React.Component {renderImgClass () {switch (this.props.content.raw_name) {...}}render() {const { content, activedId } = this.props;return (<div className={`${activedId === content.id ? 'row__item row__item-active' : 'row__item'}`} id={`row_item_${content.id}`}><img src={content.img} alt="" className={this.renderImgClass()}/>{content.name}</div>)}
}
复制代码

上面是每个小方块的源码,不难看出决定每个小方块该作何显示的地方这里

${activedId === content.id ? 'row__item row__item-active' : 'row__item'}
复制代码

通过props传进来的activedId来决定轮到哪一个方块展示动效虽然我的九宫格那不叫动效,不过原理是互通的,想展示啥就尽管在这个组件里面整就好了。

抽奖逻辑

先梳理一下这类九宫格抽奖的流程,剥离那些各种附加的特效,其实本质就是随机(或指定)某个item的id为中奖id,然后我们围绕着这个id确定该循环转圈的次数,最后再确保中奖框能停留在指定id的item即可。

点击按钮抽奖这个过程,我将它分成了两个部分,一个是状态检测与归零,另一个是触发抽奖方法(其实也可以写在一起,个人习惯将其分离,自己看起来比较舒服)。

  • handleBegin负责状态检测与归零
handleBegin() {if (!this.state.prizePlaying) {this.setState({prizePlaying: true})axios.post(url).then(res => {if (res.data.code === 0) {...axios.get(url2).then(res => {if (res.data.code === 0) {this.setState({...}, () => {this.setState({prizeActivedId: '',prizePrizeId: null,prizeTimes: 0,prizeActTimes: 0}, () => {this.handlePlay()})})}})} else {...}})}
}
复制代码

一开始先检测当前是否处于抽奖状态,如果不是才进行下面的请求,请求都完成后,将关于九宫格的状态都进行复原,然后才进行下一步操作。关于状态复原,个人认为这是相对便捷而且安全系数较高的做法,当然如果要保留原有的抽奖状态也是可以的,不过在用时候需要注意两个Times的关系。

  • handlePlay真正的抽奖方法
handlePlay() {let prize;switch (this.state.prizeLottery) {prize = ...}this.setState({prizePrizeId: prize,prizeActivedId: 0})let times = this.state.prizeList.length * Math.floor(Math.random() * 5 + 4)this.setState({prizeTimes: times})this.begin = setInterval(() => {let num;if (this.state.prizeActivedId === this.state.prizePrizeId && this.state.prizeActTimes > this.state.prizeTimes) {clearInterval(this.begin)...this.setState({prizePlaying: false})return}if (this.state.prizeActivedId === '') {num = 0this.setState({prizeActivedId: num})} else {num = this.state.prizeActivedIdif (num === 7) {num = 0this.setState({prizeActivedId: num})} else {num = num + 1this.setState({prizeActivedId: num})}}this.setState({prizeActTimes: this.state.prizeActTimes + 1})}, 100)
}
复制代码

确定中奖prizePrizeId,然后随机计算出一个最小的动画循环次数,然后就可以启动定时器开始动态更换prizeActivedId,随着prizePrizeId的变更RowItem也会重新渲染,也就成为了所谓的"蹬蹬蹬"效果啦。

如果看上面面的解释觉得不够详细,可以在文章末尾找到github的传送门,里面有demo源码并且有相关的注释。

前后端联调

这里主要想讲讲开始开发之前,自己对整个项目的规划(或想法),本着前端不可信原则,我们每次启动抽奖之前都应该与后端沟通,无论是次数还是最后的prizeId都不应该由前端决定。

从前端的角度说,我们大概需要两个接口:

  • ① 类似init的接口,告诉我们的次数,以及是否已经有获奖
  • ② 类似active的抽奖接口,我们告诉后端这里发起了一次抽奖 请求②接口之后接着返回给我们奖品是什么,然后我们在根据返回做前端id的转换,这样就能完成一个较为完善的闭环。

总结

本次记录的是个这两天做的小需求,也算是我首次尝试做类似的东西,相信在不远的将来会有一个大转盘等着我(微笑)

九宫格抽奖DEMO源码-React,一个用create-react-app临时搭的demo,希望会有帮助,谢谢。

基于React跑一个简易版九宫格抽奖相关推荐

  1. 项目——基于Oracle实现一个简易版的教务系统

    一.背景知识 本教务系统用户分为,学生,教师,系主任,管理员.学生具有选课功能,管理员具有排课功能.对于排课与选课考虑了简单的冲突检测,如下: 根据老师教学课表,为教学班所有的同学建立对相应课程的学习 ...

  2. 基于Flask制作一个简易版桌面监控软件

    /* 最近在B站上刷到一个视频,讲的是up主自己在上网课时和父母老师斗智斗勇,一边上课,一遍玩电脑游戏.我突然就感觉对于某些家长来说,监控电脑也许是个硬需求.市面上已经有诸如向日葵等远程监控,可以实现 ...

  3. 依赖注入[5]: 创建一个简易版的DI框架[下篇]

    为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在<依赖注入[4]: 创建一个简易版的DI框架[上篇]> ...

  4. DFiddler:A HTTP Packets Listener一个简易版的手机端的Fiddler。

    Diddler A HTTP Packets Listener一个简易版的手机端的Fiddler. Android系统需要Root权限. PIC_20140121_220503_617.jpeg PI ...

  5. 肝一波 ~ 手写一个简易版的Mybatis,带你深入领略它的魅力!

    零.准备工作 <dependencies><dependency><groupId>mysql</groupId><artifactId>m ...

  6. 实现一个简易版的微博,包含 client 和 server 两部分,并实现四个基础功能:关注、取关、发微博、获取用户微博列表

    const assert = require('assert'); const question = '实现一个简易版的微博,包含 client 和 server 两部分,并实现四个基础功能:关注.取 ...

  7. javascript实现图片轮播_手撸一个简易版轮播图(上)

    手撸一个简易版轮播图 实现原理,通过控制 swiper-warpper 容器的定位来达到切换图片的效果. 页面布局 简易版轮播图 < > 页面样式 .container{width: 60 ...

  8. 稳扎稳打Silverlight(18) - 2.0视频之详解MediaElement, 开发一个简易版的全功能播放器...

    [索引页] [×××] 稳扎稳打Silverlight(18) - 2.0视频之详解MediaElement, 开发一个简易版的全功能播放器 作者:webabcd 介绍 Silverlight 2.0 ...

  9. 【Linux】用进程控制知识做一个简易版shell

    文章目录 什么是shell 图示 分析 代码 什么是shell shell是命令行解释器的统称 当前使用的shell的名字是bash,bash其实也是一个程序 当前我使用的是centos7下实现一个简 ...

最新文章

  1. 字节跳动开源分布式训练框架BytePS,登上GitHub热榜
  2. 使用perf监控Linux内核网络丢弃的数据包
  3. 开源代码“All in One”:6 份最新「Paper + Code」等你复现 | PaperDaily #12
  4. OpenCV gapi模块实现幻灯片滑slides soble的实例(附完整代码)
  5. 动态规划(一)入门例子
  6. 分布与并行计算—生产者消费者模型实现(Java)
  7. pythonmain是什么_Python - __name__=='__main__'是干啥的,以及python -m与python的区别
  8. linux的dhcp的安装,linux下DHCP的安装配置
  9. 计算机怎么清理CAD,CAD遇到病毒怎么清理?别慌,教你四个方法搞定它
  10. git拉代码错误Can't update:no tracked branch
  11. 强化物联网连接 Silicon Labs收购Micrium
  12. 滴滴上市年营收超千亿,程维:我必须时刻保持危机感
  13. 使用 OpenGL 实现 RGB 到 YUV 的图像格式转换
  14. Tomcat服务器日志输出格式设置
  15. bulldog靶机练习思路详解
  16. Eclipse Xtend - 疯狂的Java10
  17. Windows10无法完成更新 正在撤销更改怎么解决转载
  18. Linux内核异常调试工具与方法
  19. 第八天 Python爬虫之Rquests库打码平台的简单使用
  20. 全志F1C芯片参数对比,供查阅

热门文章

  1. python笔记1-准确掌握列表和元组
  2. 服务器 设置 将 Tomcat 注册 到系统服务 及使用方法
  3. ubuntu 14 配置vsftp
  4. Resources$NotFoundException
  5. 创建自定义主机头的网站集
  6. 很WEB很2.0---ThunderBird
  7. 转贴:从现在电力短缺看今后劳动力短缺和高校破产
  8. linux系统常用操作命令
  9. linux/work
  10. BCH升级在即,什么是OP_CHECKDATASIG和Canonical Transaction Ordering(一)