智能助手 

外观
FLIP 是 First, Last, Invert, Play 首字母缩写。
改变元素的外边距
<div class="box">
<button id="btn">开始动画</button>
<div id="demo"></div>
</div>
let flag = false;
const el = document.getElementById("demo");
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
// first
const start = getPosition(el);
// last
if (!flag) {
el.style.left = "220px";
el.style.top = "150px";
el.style.background = "green";
} else {
el.style.left = "20px";
el.style.top = "50px";
el.style.background = "red";
}
const end = getPosition(el);
// invert
const disLeft = start.left - end.left;
const disTop = start.top - end.top;
el.style.transform = `translate(${disLeft}px,${disTop}px)`;
// play
raf(() => {
el.style.transition = "1.5s";
el.style.transform = "none";
flag = !flag;
});
});
function getPosition(el) {
return el.getBoundingClientRect();
}
function raf(callback) {
requestAnimationFrame(() => {
requestAnimationFrame(callback);
});
}
.box {
height: 200px;
position: relative;
}
#demo {
position: absolute;
left: 20px;
top: 50px;
width: 50px;
height: 50px;
background: red;
}
<button id="btn">开始动画</button>
<div id="container"></div>
const btn = document.getElementById("btn");
const container = document.getElementById("container");
const docFragment = window.document.createDocumentFragment();
for (let i = 1; i < 17; i++) {
let div = window.document.createElement("div");
div.textContent = i;
div.classList.add("item");
if ([6, 7, 10, 11].includes(i)) {
div.classList.add("red");
}
docFragment.appendChild(div);
}
container.appendChild(docFragment);
btn.addEventListener("click", () => {
first(container);
const all = last(container);
invert(all);
play(all);
});
// first
function first(container) {
const all = [...container.children];
all.forEach((item, i) => {
// 初始化动画
item.style.transition = "none";
const rect = item.getBoundingClientRect();
item.startX = rect.left;
item.startY = rect.top;
});
}
// last
function last() {
const all = [...container.children];
const len = all.length;
// 改变元素位置
all.forEach((item, i) => {
const newIndex = Math.floor(Math.random() * len);
if (newIndex !== i) {
const nextDOM = item.nextElementSibling;
container.insertBefore(item, all[newIndex]);
container.insertBefore(all[newIndex], nextDOM);
}
});
// 记录改变后的位置
all.forEach((item, i) => {
const rect = item.getBoundingClientRect();
item.currentX = rect.left;
item.currentY = rect.top;
});
return all;
}
// invert
function invert(all) {
all.forEach((item, i) => {
item.style.transform = `translate(${item.startX - item.currentX}px, ${
item.startY - item.currentY
}px)`;
});
}
// play
function play(all) {
raf(() => {
all.forEach((item, i) => {
item.style.transition = "1s";
item.style.transform = "none";
});
});
}
function raf(callback) {
requestAnimationFrame(() => {
requestAnimationFrame(callback);
});
}
#container {
margin-top: 10px;
display: grid;
width: 220px;
height: 220px;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 1fr);
}
.item {
width: 50px;
height: 50px;
background-color: pink;
text-align: center;
line-height: 50px;
}
.red {
background: red;
}
版权归属:tuyongtao1