在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 {
width: 600px;
height: 400px;
background: #000000;
margin: 50px auto;
position: relative;
}
.disc {
display: block;
width: 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_width: box_width,
box_height: box_height
});
}
</script>
</body>
</html>