首页 前端知识 《jQuery》实现一个H5的九宫格抽奖,2024年最新阿里常见面试题

《jQuery》实现一个H5的九宫格抽奖,2024年最新阿里常见面试题

2024-06-11 09:06:43 前端知识 前端哥 941 499 我要收藏

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
img

正文

$(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);

for(let el of arr){

if(radomNum >= el.percent[0] && radomNum <= el.percent[1]){

return el;

}

}

}

转动动画


转动动画是通过div的背景色的顺时针的顺序切换实现的,通过不断的顺时间变化给人一种转动的感觉,而启动动画就是开始每一个变化的间隔都较长,然后变化的间隔逐渐变短,造成加速的视觉过程;减速同理,也就是间隔变长导致了转速下降的视觉错觉;

这是一个选中div的函数,因为不管是加速,匀速,减速,都是需要选中div改变背景色,因此这个过程抽离了出来,方便在三个速度中调用

//选中dom对象

function runAnimate(dom){

if(i<7){

i++;

}

else{

i=0;

}

$(‘#’+dom).children().removeClass(‘selected’).eq(i).addClass(‘selected’);

}

加速动画

//不管是概率抽奖还是指定奖品抽奖,最终都会执行到这个加速动画

//设定时间

const normalTime = 50,maxTime=300;

//转动次数

const normal = 2400/normalTime;

let timer,i,t;

let v;

const a=-20;

//执行动画,加速

function speedUp(dom,index){

//将dom传递进去,当然也可以直接将dom写进选中的函数里

runAnimate(dom);

//如果间隔已经达到设定的值,那么就执行匀速动画函数

if(v<=normalTime){

v=normalTime;

clearTimeout(timer);

speedNormal(dom,index);

}

//else里面则是间隔还没有达到设定的要求,还需要继续循环加速

else{

v = v+a;

timer = setTimeout(()=>{

speedUp(dom,index)

}, v);

}

}

总结

大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
e;

clearTimeout(timer);

speedNormal(dom,index);

}

//else里面则是间隔还没有达到设定的要求,还需要继续循环加速

else{

v = v+a;

timer = setTimeout(()=>{

speedUp(dom,index)

}, v);

}

}

总结

大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-1XTELYTO-1713206667530)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

转载请注明出处或者链接地址:https://www.qianduange.cn//article/11930.html
标签
评论
发布的文章

HTML5-本地存储浅谈

2024-06-19 08:06:18

JS实现倒计时功能

2024-06-19 08:06:34

HTML黑客帝国字母雨

2024-06-11 09:06:45

每天一篇之HTML(2)

2024-06-19 08:06:26

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!