在JS中元素运动的时候我们需要使用一些运动的操作,这里作者自己设计了一个简单的运动函数,可以实现匀速和缓冲运动效果。
/*
* @Descripttion:
* @version:
* @Author: 小小荧
* @Date: 2020-03-17 18:01:21
* @LastEditors: 小小荧
* @LastEditTime: 2020-03-17 19:11:01
*/
/**
* 多属性的动画函数
* @param {*} ele 需要运动的节点
* @param {*} attr_options 传入的是一个需要运动的属性包括运动的目标值,操作的节点属性
* @param {*} timefn 运动的形式,默认是缓冲运动
* @param {*} speed 运动的速度
*/
function animate(ele, attr_options, callback, timefn = "swing", speed = 5) {
// 我们需要把传入的options处理成
/*
{“width : {
target : 200,
iNow : 100
}}这个形式
*/
for (var attr in attr_options) {
attr_options[attr] = {
target: attr === "opacity" ? parseInt(attr_options[attr] * 100) : attr_options[attr],
// 需要计算得到
iNow: attr === "opacity" ? parseInt(getComputedStyle(ele)[attr] * 100) : parseInt(getComputedStyle(ele)[attr])
}
}
// 判断是不是匀速运动
if (timefn === "liner") {
speed = attr_options[attr].iNow < attr_options[attr].target ? Math.abs(speed) : -Math.abs(speed);
}
// 为了防止每个节点的定时器冲突,每次进入的时候我们需要先清理下节点的定时器
clearInterval(ele.timer);
// 然后再去设置定时器
ele.timer = setInterval(function () {
// 因为是多属性运动,我们首先循环遍历每一个属性
for (var attr in attr_options) {
var target = attr_options[attr].target;
var iNow = attr_options[attr].iNow;
// 计算speed 判断是不是缓冲运动
if (timefn === "swing") {
speed = (target - iNow) / 20;
// 为了防止速度无法达到一个整数
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
}
// 运动之中条件的判断
if (Math.abs(target - iNow) <= Math.abs(speed)) {
if (attr === "opacity") {
ele.style[attr] = target / 100;
} else {
ele.style[attr] = target + "px";
}
// 每次一个属性运动完成之后我们就直接将它删除
delete attr_options[attr];
// 每次都去循环看一下还有没有属性需要操作
for (var num in attr_options) {
return false;
}
// 清理定时器 因为我们是一个定时器绑定多个属性操作所以我们需要保证所有的属性都完成之后我们才可以将定时器清除
clearInterval(ele.timer);
// 等结束之后我们需要判断这个回到函数是函数我们就回调
typeof callback === "function" ? callback() : ""
} else {
attr_options[attr].iNow += speed;
if (attr === "opacity") {
ele.style[attr] = attr_options[attr].iNow / 100;
} else {
ele.style[attr] = attr_options[attr].iNow + "px";
}
}
}
}, 30);
}
参数解释
animate(ele, attr_options, callback, timefn(可选), speed(可选))
ele : 需要运动的元素节点
att_options:需要运动的元素节点
callback : 回调函数,是运动结束之后需要完成的操作
timefn : 可选参数,是值运动的效果 可选liner匀速运算,swing缓冲运算
speed : 可选参数,值运动的速度
演示
<!DOCTYPE html>
<!--
* @Descripttion:
* @version:
* @Author: 小小荧
* @Date: 2020-03-17 21:44:07
* @LastEditors: 小小荧
* @LastEditTime: 2020-03-22 14:19:09
-->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
}
.container {
600px;
height: 400px;
background: #000000;
margin: 50px auto;
position: relative;
}
.disc {
display: block;
4px;
height: 4px;
background: #ffffff;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
opacity: 1;
border: 1px solid #ffffff
}
</style>
</head>
<body>
<div class="container">
</div>
<script src="./多属性运动.js"></script>
<script>
// 定义一个小圆点的构造函数
function Disc(options) {
this.init(options)
}
// 初识化的方法
Disc.prototype.init = function (options) {
// 这个就是初始化的时候这是一个计数的属性,后面可以用来判断就完成透明的切换
this.count = 0;
// 父盒子的宽度
this.box_width = options.box_width;
// 父盒子的高度
this.box_height = options.box_height;
// 父盒子
this.box_ele = options.box_ele;
// 创建节点
this.createEle();
}
// 生成随机坐标
Disc.prototype.randomPos = function () {
// x 坐标
this.x = Math.round(Math.random() * (this.box_width - this.disc_ele.offsetWidth));
// y坐标
this.y = Math.round(Math.random() * (this.box_height - this.disc_ele.offsetHeight));
}
// 创建每一个元素的函数
Disc.prototype.createEle = function () {
// 创建每一个小圆点的元素节点
this.disc_ele = document.createElement("span");
// 设置className
this.disc_ele.className = "disc";
// 像父盒子中追加元素节点
this.box_ele.appendChild(this.disc_ele);
// 获取随机的xy值
this.randomPos();
// 设置这个元素的xy值
this.disc_ele.style.left = this.x + "px";
this.disc_ele.style.top = this.y + "px";
// 创建完成之后我们就需要移动了
this.move(this.disc_ele);
}
// 执行运动函数
Disc.prototype.move = function (ele) {
// 我们默认opacity是0.6的透明度
var opacity = 0.6;
if (this.count % 2) {
// 如果运动的次数是奇数,我们就让这个透明度变为1
opacity = 1;
}
// 每次执行都需要count++
this.count++;
this.randomPos();
animate(ele, {
top: this.y,
left: this.x,
opacity: opacity
}, () => {
this.move(ele);
});
}
var box_ele = document.querySelector(".container");
var box_width = box_ele.offsetWidth;
var box_height = box_ele.offsetHeight;
//循环穿件元素节点
for (var i = 0; i < 80; i++) {
// 创建对象
var disc = new Disc({
box_ele: box_ele,
box_ box_width,
box_height: box_height
});
}
</script>
</body>
</html>