求助,转盘抽奖bug解决?关于forEach关于异步

我预期的效果是这样的,arr中存放的是永远不可能被选中的人,然后每次选中之后将其push到arr中
而在前台展示上,始终以全部人名names中进行旋转
我的代码如下:

var names = ['姓名A', '姓名B', '姓名C', '姓名D'];
var arr = ['姓名C'];
var box3d = document.querySelector('#box3d');
var elData = document.createDocumentFragment();
var boxNames = box3d.children;
// 循环插入
names.forEach(function (item) {
  var li = document.createElement("li");
  // li.innerHTML = item.name;
  li.innerHTML = item;
  elData.appendChild(li);
});
box3d.appendChild(elData);
// 初始
var deg = 360 / boxNames.length;
var innerDeg = (180 - deg) / 2;
var disR = Math.tan(innerDeg * Math.PI / 180) * 25;
Array.from(boxNames).forEach(function (item, index) {
  item.style.transform = "rotateX(" + index * deg + "deg) translateZ(" + disR + "px)";
});
// 抽奖
var btn = document.querySelector('.btn');
var box3d = document.querySelector('#box3d');
var boxNames = box3d.children;
// 点击事件
btn.onclick = function () {
  var nub = Math.floor(Math.random() * names.length);
  var deg = 360 / boxNames.length;
  var round = Math.round(Math.random() * 5) + 2;
  var targetDeg = -deg * nub + round * 360;
  var time = Math.abs(targetDeg) * 2;
  css(box3d, "rotateX", 0);
  // 终止继续
  if (names.length - arr.length < 0) {
    console.log('无法再继续了')
    return false
  }
  // 筛选,将过滤掉arr中的人,且保持原对象不变
  console.log(1, names[nub], nub, targetDeg)
  arr.forEach(function (item) {
    if (names[nub] == item) {
      nub = Math.floor(Math.random() * names.length);//第一个问题,当第一遍匹配出数据后nub重新获取随机值,但是当第二遍依然匹配中后,如何再次重新获取随机值?(尝试将forEach写成递归,但是无法从forEach中return得到值)
      targetDeg = -deg * nub + round * 360;
      console.log(2, names[nub], nub, targetDeg)
    }
  })
  console.log(3, names[nub], nub, targetDeg)//第二个问题,console如何在forEach之后执行
  //将不在arr中的人添加如arr
  arr.push(names[nub])
  // 滚动函数
  mTween({
    el: box3d,
    duration: time,
    fx: "easeOutStrong",
    attrs: {
      rotateX: targetDeg
    },
    cb: function () {
      // alert("中奖的是:" + names[nub].name);
      console.log("中奖的是:" + names[nub]);
      // var index = arr.indexOf(names[nub]) + 1;
    }
  })
}

经测试,暂时定位的问题是这里:

  console.log(1, names[nub], nub, targetDeg)
  arr.forEach(function (item) {
    if (names[nub] == item) {
      nub = Math.floor(Math.random() * names.length);
      targetDeg = -deg * nub + round * 360;
      console.log(2, names[nub], nub, targetDeg)
    }
  })
  console.log(3, names[nub], nub, targetDeg)

1.第一个问题,当第一遍匹配出数据后nub重新获取随机值,但是当第二遍依然匹配中后,如何再次重新获取随机值?(尝试将forEach写成递归,但是无法从forEach中return得到值)?
2.第二个问题,console3如何在forEach之后执行?

阅读 1.4k
1 个回答

可以换个思路, 为了防止抽到重复的人, 我们把要抽的人的数组随机打乱, 每次抽就取数组第一个.

var arr = [1,2,3,4,5,6]; //所有
var passArr = [1,2]; //不会选中的项
//_arr 是一个已被打乱的,可被选的项
var _arr = arr.filter(x=>!passArr.includes(x)).sort((x,y)=>Math.random()-0.5); //随机打乱数组, 相当于抽签

//抽选函数
function cj(n){
    n = n || 1; //默认抽一个;
    //_arr.sort((x,y)=>Math.random()-0.5); //实在心里过不支就加上这一句, 抽前打乱一次
    return _arr.splice(0,n);
}
推荐问题