func(jQuery,plugin)
})(this,function(jQuery,plugin){
const defaultName = ‘谢谢惠顾’;
//奖品列表上限数量8
const maxListNumber = 8;
const puginID = ‘oliverPrizeDraw’;
const row = 3;
const column = 3;
let flg=false;
let this;
$.fn[plugin] = function(params) {
let _this = this;
if(!isObj(params)) throwError(‘传入的参数必须是一个对象’);
//此时的createDOMList仅仅是一个数组,尚未插入DOM树中
let createDOMList = createDomListArr(params.prizeList);
//在createDOM()函数中创建DOM,并返回了中间“开始”按钮的ID,这样方便给按钮添加点击事件
let btn = createDOM(createDOMList,_this);
}
//根据参数,按顺序创建了9个div,保存在了数组中返回
function createDomListArr(arr){
let newArr = [];
arr.forEach((el,index) => {
newArr.push(<div data-id='${el.id}' index='${index}'>${el.name}</div>
)
})
return newArr;
}
//创建DOM
function createDOM(list,dom){
//创建了一个div,作为外框的父级元素
let divContainer = <div id='${puginID+'Container'}'></div>
;
//将外框加入页面上
dom.append(divContainer);
//创建一个div用来存放8个抽奖元素
let div = <div id='${puginID+'Box'}'></div>
;
//将用来存放抽奖元素的div加入外框下
$(‘#’+puginID+‘Container’).append(div);
//获得到上面刚刚加入到页面上用来存放抽奖元素的box
let box = $(‘#’+puginID+‘Box’);
//将上面生成的8个抽奖元素统统放进去,此时里面的抽奖元素还没有最终排列成需要的形态
box.append(list);
//获得8个抽奖元素
let children = box.children();
//对每个抽奖元素的大小进行设定,每个方块的大小都设定成父元素的三分之一
//里面的-4是因为需要做间隔
children.css({
‘width’:box.width()/row-4+‘px’,
‘height’:box.height()/column-4+‘px’,
‘line-height’:box.height()/column-4+‘px’,
})
}
//是否是个对象
function isObj(obj){
return Object.prototype.toString.call(obj) === ‘[object Object]’;
}
},‘prizeDraw’)
当执行到这里的时候,已经创建好了8个div,并且每个div的大小都已经设置成外框的三分之一大小了(其他具体的样式,比如间隔,背景色等等都是通过css设置的);
开始按钮和排列位置
当时的基本思路是,一个父级元素div作为外框,下面有两部分:
-
第一部分是中间的开始按钮;
-
第二部分是一个div,这个div下有按钮周围一圈的奖品;
这两部分一共9格,采用的都是绝对定位,只有绝对定位可以按照意愿随意摆放位置;
//创建DOM
function createDOM(list,dom){
/*
第一小节代码放这里
*/
//-----------------分割线--------------//
//对8个元素每个都执行一次位置排放
children.each((index,el)=>{
//第0-1个,也就是第1、第2个方块
//离顶部的距离是0,每一个方块相对前面一个方块离左侧的距离是多一个方块的宽度
if(index >= 0 && index < (row-1)){
$(el).css({
‘top’:0,
‘left’:index*(box.width()/row)+‘px’
})
}
//第3,第4个方块,离右侧的距离是0,离顶部是逐一多一个方块的距离
//
else if(index>=row-1 && index<row+column-1){
$(el).css({
‘right’:0,
‘top’:(index-2)*(box.height()/column)+‘px’
})
}
//第5,第6个方法,离底部的距离是0,离右侧的距离逐一多一个方块的距离
else if(index>=row-1+column&&index<(2*row+column-2)){
$(el).css({
‘bottom’:0,
‘right’:(index-(row+column-2))*(box.width()/row)+‘px’
})
}
//第7,第8个,离左侧的距离是0,距离顶部的距离是处于第二排,第三排
else{
$(el).css({
‘top’:(index-(2*(row+column)-6))*(box.height()/column)+‘px’,
‘left’:0
})
}
})
//创建开始按钮
let startBtn = <span id='${puginID+'StartBtn'}' class='start-btn start-btn-able'>开始</span>
;
//将按钮加入DOM
box.parent().append(startBtn);
给按钮设置样式,将其置于正中间
$(‘#’+puginID+‘StartBtn’).css({
‘width’:box.width()/row-4+‘px’,
‘height’:box.height()/column-4+‘px’,
‘line-height’:box.height()/column-4+‘px’,
‘left’:box.width()/row+‘px’,
‘top’:box.height()/column+‘px’,
// ‘transform’:‘translate(-50%,-50%)’
})
//返回按钮
return {
startBtn:puginID+‘StartBtn’,
boxId:puginID+‘Box’
}
}
在这个阶段,需要给开始按钮绑定点击事件,点击后可以启动转动动画,当然在启动之前,必须对奖品数组进行一系列检测,如果有错误进行简单的处理,最终返回一个我们需要的抽奖数组,这个最终的抽奖数组才上面插入DOM的div,也就是说,实际上对传入的参数进行检测这一步应该放在排列位置之前;
有了最终的合法的抽奖数组,那么就可以根据需求,筛选最终奖品;
检测参数
$.fn[plugin] = function(params) {
let _this = this;
if(!isObj(params)) throwError(‘传入的参数必须是一个对象’);
//再创建之前,需要先对传入的参数做一次检测,如果参数错误,长度错误可以及时补齐或抛出异常
params.prizeList = finalList(params.prizeList);
//此时的createDOMList仅仅是一个数组,尚未插入DOM树中
let createDOMList = createDomListArr(params.prizeList);
let btn = createDOM(createDOMList,_this);
}
//检测参数
function finalList(arr){
//存在且必须是数组
if(!(arr && Array.isArray(arr))){
let newArr = [];
for(let i = 0 ; i < maxListNumber ; i++){
//数组每一项都有名字,id和概率
newArr.push({
name:defaultName,
id:puginID + i,
percent:100 / maxListNumber
});
}
//返回数组
return newArr;
}
//概率这一项必须是数字
arr.forEach((el)=>{
if(!isNumber(el.percent)){
throwError(‘奖品列表的percent的值必须是数字类型,当前ID为:’+el.id+’ 的percent值不是数字’);
}
})
//奖品列表长度必须是8
if(arr.length === maxListNumber){
//概率的总和必须是100,不能8个方块的概率加起来超出100了
let percent = resultPro(arr);
if(percent !== 100) throwError(‘奖品列表的概率和必须是100,当前是:’+percent);
return arr;
}
else{
//假如传入的参数的长度超过了8,提示
let length = maxListNumber - arr.length;
length = length > 0 ? length : throwError(‘奖品列表的数量上限是:’+maxListNumber+‘,当前是:’+arr.length);
//当前概率和
let current = resultPro(arr);
if(current>100) throwError(‘奖品列表的概率和必须小于100,当前是:’+current);
for(let i = 0 ; i < length ; i++){
arr.push({
name:defaultName,
id:puginID + i,
percent:(100 - current) / length
})
}
//返回打乱的数组,不能是输入的奖品顺序是什么就是什么
return arr.sort(randomArr);
}
}
//判断当前的奖品列表的概率总计
function resultPro(arr){
if(!Array.isArray(arr)) throwError(‘resultPro的参数必须是数组’);
let result = 0;
arr.forEach((el) => {
el.percent && isNumber(el.percent)? result = result + el.percent : ‘’;
})
return result;
}
//打乱数组
function randomArr(a,b){
return Math.random()>.5 ? -1 : 1;
}
//抛出异常
function throwError(val){
throw new Error(val)
}
等检测完,此时返回的抽奖数组就是一个完整的奖品数组了,在第一步创建div的时候就可以按照这个顺序直接创建div并排列;
点击开始按钮
到这一阶段,就需要给开始按钮添加点击事件了,并且点击后开始按钮进入disable的状态,不然连续点击就会出现问题,并且,点击“开始”按钮后,会出现两种情况:
-
存在指定奖品,也就是俗称的黑幕,不管谁抽,都是谢谢惠顾之类的;
-
不存在指定奖品,那么就会按照设定的概率进行抽奖;
$.fn[plugin] = function(params) {
let _this = this;
if(!isObj(params)) throwError(‘传入的参数必须是一个对象’);
//生成抽奖数组
params.prizeList = finalList(params.prizeList);
let createDOMList = createDomListArr(params.prizeList);
//创建DOM并返回按钮ID
let btn = createDOM(createDOMList,_this);
let boxChinldren = btn.boxId;
$(‘#’+btn.startBtn).on(‘click’,function(){
this = this;
//通过flg开关,判断是否可以点击
if(!flg){
//添加不可点击时的样式;
$(this).addClass(‘start-btn-disable’).removeClass(‘start-btn-able’);
flg = true;
//判断是否有指定奖品ID
//假如有指定奖品,那么概率抽奖就不会生效,假如没有,那么就进行概率抽奖
if(params.finalPrizeID&&isString(params.finalPrizeID)){
//判断一下设定的最终奖品id存不存在
//不要设定了一个奖品id,结果奖品列表中没有,或者有2个及2个以上的奖品
let array = [];
params.prizeList.forEach(element => {
if(element.id === params.finalPrizeID){
array.push(element);
}
})
//根据数组长度进行判断
switch(array.length){
//长度是0,那么就说明指定的id不存在,那么将进行概率抽奖
case 0:
console.log(‘指定的奖品ID在奖品列表中不存在,将按指定概率进行抽奖’);
//这个是抽奖函数,下一大节解释这个函数
targetPrize(params.prizeList,boxChinldren);
break
//长度是1,那么这个就是正常情况,这个奖品就是最终奖品
case 1:
let name = array[0].name?array[0].name:‘默认名字’;
console.log(‘指定奖品为:’+name);
targetPrize(array[0],boxChinldren);
break
//长度超出了1个,那么就是存在多个相同id的最终奖品,其实也可以进行概率抽奖
default:
throwError(‘指定的最终奖品ID在奖品列表中不唯一’);
break;
}
}
//没有指定奖品,那么就正常进行概率抽奖
else{
console.log(‘无指定奖品,将按指定概率进行抽奖’);
targetPrize(params.prizeList,boxChinldren);
}
}
})
}
在上一大节中,通过targetPrize函数,进行抽奖,其中第一个参数:
-
如果是一个对象,那么就代表直接传递过来了最终奖品,那么就不需要通过函数去计算哪个是最终奖品;
-
如果是一个数组,那么代表使用者并没有设定最终奖品,需要按照概率进行随机抽取;
其中,如果是数组,大致上就是将数组中的每一项奖品的概率转成一个区间,比如:第一个奖品的概率是10,那么在100中,随机数0-9指的就是这个奖品,如果第二个奖品的该也是10,那么转换后10-19就是这个奖品,第三个奖品的概率是30,那么它所对应的区间就是20-59,以此类推;
这样就将奖品的概率平铺满了100,到这里的抽奖只需要随机数一个0-100的数字,这个数字在哪个区间,就代表抽中了哪个奖品;
//执行抽奖,传入的正常抽奖或者是指定奖品,dom列表
function targetPrize(params,dom){
//如果是对象,执行指定奖品,如果是数组,执行概率抽奖
isObj(params)?
pointPrize(params,dom):
Array.isArray(params)?
percentPrize(params,dom):
throwError(‘targetPrize()参数错误’);
}
//指定奖品
function pointPrize(params,dom){
//指定产品的位置
let ax = targetIndex(params,dom)
console.log(params);
speedUp(dom,ax);
}
//概率抽奖
function percentPrize(params,dom){
//将概率转成数组区间
let newArr = arrayPercent(params);
//获得最终奖品
let percent = objPercent(newArr);
console.log(percent);
//指定产品的位置
let ax = targetIndex(percent,dom)
speedUp(dom,ax);
}
//将概率转成区间数组
function arrayPercent(arr){
let sum = 0;
let newArr=[];
arr.forEach((el)=>{
el.percent&&isNumber(el.percent)?
newArr.push({
name:el.name,
id:el.id,
percent:[sum,(sum+el.percent)===100?(sum=sum+el.percent):(sum=sum+el.percent)-1]
}):‘’;
})
return newArr;
}
//选出一个随机数并返回指定区间的对象
function objPercent(arr){
let radomNum = Math.floor(Math.random() * 100);
console.log(radomNum);
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
//选出一个随机数并返回指定区间的对象
function objPercent(arr){
let radomNum = Math.floor(Math.random() * 100);
console.log(radomNum);
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Apxjoei1-1715720408871)]
[外链图片转存中…(img-3AOyolJ6-1715720408871)]
[外链图片转存中…(img-FUkOOC32-1715720408872)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!