2020年已悄然来临,一年又这样白白浪费了,年末将至,来了一个小任务,实现年会的随机抽人效果,需求:所有的人都在屏幕上四处漂泊,点击抽人后,加快速度,5秒后,抽中的人跑向中间,其他所有人,飞出屏幕外,并保证每个人抽中的概率只有一次。看到这个需求后,对于一个Android开发者而言,懵逼了!不过还是细细钻研了一番,最终实现效果如下,当然,有参考他人的思路,效果如下:
这里主要说下实现思路,主要用到了requestAnimationFrame这个函数,以及JQery里animate动画,数据源,自己写了一个txt文件,里面存储所有人姓名。
{
"result":[
"张三",
"李四",
"王五",
"赵六",
"闫七",
"李八",
"李九",
"李十",
"张十一",
"钱十二",
"孙大",
"周二",
"吴三",
"郑四",
"王洛",
"冯九",
"都偶",
"某某"
],
"message":"成功",
"status":"0000"
}
页面其实很简单,一个用于动态添加到的p标签,还有两个div按钮,页面底部的js文件, 首先使用JQuery获取了所有人的姓名,然后赋值给了p标签,需要注意的是,获取完名字后,这里我做了一个遍历,即让每个名字后都带了一个空格,然后调用了animate.js中的Animate对象。
随机抽人
随机抽人
重置
animate.js里,由于前边设置的文字携带了空格,这里对于设置的文字做了分割,动态创建span标签,并定义了一个随机的集合,具体看下面代码:
var isRun = true;
function Animate(id) {
var ele = document.getElementById(id),
eletext = ele.innerText,
arr = eletext.split(" "),
_this = this;
this.resetTime = 10; //最大值100
this.color = [
'#f44336', '#e91e63', '#9c27b0',
'#673ab7', '#3f51b5', '#2196f3',
'#03a9f4', '#00bcd4', '#009688',
'#4caf50', '#8bc34a', '#cddc39',
'#ffeb3b', '#ffc107', '#ff9800',
'#ff5722', '#795548', '#9e9e9e',
'#607d8b'
];
this.randomColor = function () {
var colorIndex = Math.floor(this.color.length * Math.random());
return this.color[colorIndex];
};
this.posRangencala = function () {
return ele.hasAttribute("ele-range") ? {
minRange: {
x: ele.getBoundingClientRect().left,
y: ele.getBoundingClientRect().top
},
maxRange: {
x: ele.getBoundingClientRect().right,
y: ele.getBoundingClientRect().bottom
}
} : {
minRange: {
x: 0,
y: 0
},
maxRange: {
x: document.documentElement.clientWidth,
y: document.documentElement.clientHeight
}
}
};
this.spanArr = (function () {
ele.innerHTML = "";
var spanArr = [];
arr.forEach(function (value, index) {
var spanDom = document.createElement("span");
spanDom.style.display = "inline-block";
spanDom.innerHTML = value;
spanDom.style.position = "relative";
spanDom.style.color = _this.randomColor();
spanDom.style.fontSize = "26px";
spanDom.own = {
pos: {
x: 0,
y: 0
},
ran: {
x: -.5 + Math.random(),
y: -.5 + Math.random()
},
speed: {
x: 1,
y: 1
},
dir: {
x: 1,
y: 1
}
};
ele.appendChild(spanDom);
spanArr.push(spanDom);
});
return spanArr;
})();
this.spanOrigin = function () {
this.spanArr.forEach(function (value, index) {
value.own.realPos = {
minx: value.getBoundingClientRect().left,
maxx: value.getBoundingClientRect().right,
miny: value.getBoundingClientRect().top,
maxy: value.getBoundingClientRect().bottom
}
});
this.posRangen = this.posRangencala();
};
this.spanOrigin();
this.resetpos = function () {
this.spanOrigin();
this.spanArr.forEach(function (span, index) {
if (span.own.realPos.minx + span.own.pos.x < _this.posRangen.minRange.x) span.own.pos.x = 0;
if (span.own.realPos.maxx + span.own.pos.x > _this.posRangen.maxRange.x) span.own.pos.x = 0;
if (span.own.realPos.miny + span.own.pos.y < _this.posRangen.minRange.y) span.own.pos.y = 0;
if (span.own.realPos.maxy + span.own.pos.y > _this.posRangen.maxRange.y) span.own.pos.y = 0;
})
};
this.floatText = function () {
this.spanArr.forEach(function (span, index) {
if (span.own.realPos.minx + span.own.pos.x < _this.posRangen.minRange.x || span.own.realPos.maxx + span.own.pos.x > _this.posRangen.maxRange.x) {
span.own.dir.x = -span.own.dir.x;
}
if (span.own.realPos.miny + span.own.pos.y < _this.posRangen.minRange.y || span.own.realPos.maxy + span.own.pos.y > _this.posRangen.maxRange.y) {
span.own.dir.y = -span.own.dir.y;
}
if (isRun) {
timeOut(span, 0);
} else {
for (var a = 0; a < 20; a++) {
timeOut(span, 10);
}
}
})
};
function timeOut(span, time) {
setTimeout(function () {
span.own.pos.x += span.own.ran.x * span.own.speed.x * span.own.dir.x;
span.own.pos.y += span.own.ran.y * span.own.speed.y * span.own.dir.y;
span.style.transform = "translateX(" + span.own.pos.x + "px) translateY(" + span.own.pos.y + "px)";
}, time);
}
var boolClick = true;
this.floatBack = function () {
this.spanArr.forEach(function (value, index) {
var text = value.innerText;
var x = value.own.pos.x - value.own.pos.x * _this.resetTime / 100 - 100;
var y = value.own.pos.y - value.own.pos.y * _this.resetTime / 100 - 100;
var vip = localStorage.getItem("vip");
if (vip == text) {
if (boolClick) {
var tTop = value.getBoundingClientRect().top;
var tLeft = value.getBoundingClientRect().left;
var sizeW = winW / 2;
var sizeH = winH / 2;
var s = value.getBoundingClientRect().width / 3;
var endX = sizeW - tLeft - s * 2;
var endY = sizeH - tTop - 36;
$(value).animate({top: endY, left: endX, fontSize: '36px'});
boolClick = false;
}
} else {
value.style.transform = "translateX(" + x + "px) translateY(" + y + "px)";
setTimeout(function () {
$(value).animate({top: '-150px'});
}, 200);
}
});
if (this.resetTime === 100) {
cancelAnimationFrame(_this.send);
return true;
} else {
this.resetTime += 5;
}
};
this.restart = function () {
this.spanArr.forEach(function (value, index) {
value.own.pos.x = 0;
value.own.pos.y = 0;
})
};
this.render = {
run: function () {
_this.sren = requestAnimationFrame(_this.render.run);
_this.floatText();
},
end: function () {
_this.send = requestAnimationFrame(_this.render.end);
_this.floatBack();
},
killer: function (bool) {
if (bool) {
isRun = true;
window.location.reload();
} else {
isRun = false;
setTimeout(function () {
var that = _this;
cancelAnimationFrame(that.sren);
that.render.end();
}, 5000);
}
}
};
var winW = 0;
var winH = 0;
window.onresize = function () {
_this.resetpos();
};
getWh();
function getWh() {
winW = document.body.offsetWidth;
winH = document.documentElement.clientHeight;
}
}
animate.css
* {
margin: 0;
padding: 0;
}
html {
font-family: "微软雅黑";
font-size: 20px;
}
::-webkit-scrollbar {
overflow-x: hidden;
}
body {
background: #000;
overflow: hidden;
}
p {
width: 80%;
margin: 100px auto 30px;
line-height: 1.5;
}
.div_bottom div {
width: 100%;
height: 50px;
background: orange;
color: #ffffff;
font-family: "微软雅黑";
border-radius: 10px;
border: 1px solid orange;
text-align: center;
line-height: 50px;
cursor: pointer;
}
.reset {
margin-top: 20px;
}
.div_bottom {
position: absolute;
bottom: 5%;
width: 10%;
height: 120px;
left: 45%;
}
全部都是已写好的代码,可以直接复制使用,只需要更改txt文件里的名字即可。