目录
目标:
编辑1、确定思路
2、创建网格
3、设置随机位置
4、创建时间轴动画
完整代码:
目标:
实现自动选点,对该点进行先缩小后放大如何回到比其他点大一点的状态,并以该点从外向内放大
1、确定思路
2、创建网格
知识点:
createDocumentFragment()方法:
是用来创建一个虚拟的节点对象,或者说,是用来创建文档碎片节点。它可以包含各种类型的节点,在创建之初是空的。
当需要添加多个dom元素时,如果先将这些元素添加到DocumentFragment中,再统一将DocumentFragment添加到页面,会减少页面渲染dom的次数,效率会明显提升。
效果:
3、设置随机位置
知识点:
anime.stagger——交错动画
anime.stagger(value, options) //options 是一个对象类型: from: startingPosition ————从哪里开始 direction: '反向' ————运动反向 grid: [rows, columns] ————网格 anime.stagger(value, {grid: [rows, columns], axis: 'x'}) //axis设置为x,表示将一整行设置为整体 //设为y,会将一整列设置为整体 //例如: delay: anime.stagger(200, {grid: [14, 5], from: 'center'})
index:设置随机的起始点
使用anime.set方法给小红点cursor设置移动位置
效果:
4、创建时间轴动画
(1)先实现红色小圆点的动画效果
用keyframes表示帧动画,用数组接收,每一帧是一个对象。
设置时间轴: anime.timeline.add(parameters, offset); //parameters 动画相关的参数————对象类型 //offset 时间偏移量————字符串或者数字类型 // 字符串类型表示相对时间偏移,数字类型表示绝对偏移量
效果:
(2)实现边上的白点动态效果
targets目标为小白点
(3)融合两个点的效果
这两个点不是同时执行的,要让他们有一个交错的效果,给第二个动画设置delay。
第二个动画不是等到第一个动画结束才开始,是在整个时间轴执行30ms之后开始的,设置Number类型的时间偏移量。
效果:
(4)创建第3个动画,让红色的圆点继续向下平移
(5)让小点一直运动
现在看到的效果就是,它运动完一个点,跑到下一个点的时候就停止了,我们如何让他一直是动态的呢?没错,我们需要循环。
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
background-color: #F6F4F2;
color: #252423;
}
body {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
width: 100%;
height: 100vh;
}
.animation-wrapper {
width: 80%;
padding-bottom: 40%;
}
.stagger-visualizer {
position: absolute;
width: 1100px;
height: 550px;
transform-origin: left top;
}
.stagger-visualizer .dots-wrapper {
transform: translateZ(0);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.stagger-visualizer .dot {
position: relative;
z-index: 1;
width: 23px;
height: 23px;
margin: 16px;
background-color: currentColor;
border-radius: 50%;
}
@media (min-width: 740px) {
.stagger-visualizer .dot {
background-color: transparent;
background-image: linear-gradient(180deg, #FFFFFF 8%, #D3CDC6 100%);
}
}
.stagger-visualizer .cursor {
position: absolute;
top: 0px;
left: 0px;
width: 37px;
height: 37px;
margin: 9px;
background-color: currentColor;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="animation-wrapper">
<div class="stagger-visualizer">
<div class="cursor color-red"></div>
<div class="dots-wrapper"></div>
</div>
</div>
<script src="../node_modules/animejs/lib//anime.min.js"></script>
<script>
function fitElementToParent(el, padding) {
var timeout = null;
function resize() {
if (timeout) clearTimeout(timeout);
anime.set(el, { scale: 1 });
var pad = padding || 0;
var parentEl = el.parentNode;
var elOffsetWidth = el.offsetWidth - pad;
var parentOffsetWidth = parentEl.offsetWidth;
var ratio = parentOffsetWidth / elOffsetWidth;
timeout = setTimeout(anime.set(el, { scale: ratio }), 10);
}
resize();
window.addEventListener('resize', resize);
}
var advancedStaggeringAnimation = (function () {
var staggerVisualizerEl = document.querySelector('.stagger-visualizer');
var dotsWrapperEl = staggerVisualizerEl.querySelector('.dots-wrapper');
var dotsFragment = document.createDocumentFragment();
var grid = [20, 10];
var cell = 55;
var numberOfElements = grid[0] * grid[1];
var animation;
var paused = true;
fitElementToParent(staggerVisualizerEl, 0);
for (var i = 0; i < numberOfElements; i++) {
var dotEl = document.createElement('div');
dotEl.classList.add('dot');
dotsFragment.appendChild(dotEl);
}
dotsWrapperEl.appendChild(dotsFragment);
var index = anime.random(0, numberOfElements - 1);
var nextIndex = 0;
anime.set('.stagger-visualizer .cursor', {
translateX: anime.stagger(-cell, { grid: grid, from: index, axis: 'x' }),
translateY: anime.stagger(-cell, { grid: grid, from: index, axis: 'y' }),
translateZ: 0,
scale: 1.5,
});
function play() {
paused = false;
if (animation) animation.pause();
nextIndex = anime.random(0, numberOfElements - 1);
animation = anime.timeline({
easing: 'easeInOutQuad',
complete: play
})
.add({
targets: '.stagger-visualizer .cursor',
keyframes: [
{ scale: .75, duration: 120 },
{ scale: 2.5, duration: 220 },
{ scale: 1.5, duration: 450 },
],
duration: 300
})
.add({
targets: '.stagger-visualizer .dot',
keyframes: [
{
translateX: anime.stagger('-2px', { grid: grid, from: index, axis: 'x' }),
translateY: anime.stagger('-2px', { grid: grid, from: index, axis: 'y' }),
duration: 100
}, {
translateX: anime.stagger('4px', { grid: grid, from: index, axis: 'x' }),
translateY: anime.stagger('4px', { grid: grid, from: index, axis: 'y' }),
scale: anime.stagger([2.6, 1], { grid: grid, from: index }),
duration: 225
}, {
translateX: 0,
translateY: 0,
scale: 1,
duration: 1200,
}
],
delay: anime.stagger(80, { grid: grid, from: index })
}, 30)
.add({
targets: '.stagger-visualizer .cursor',
translateX: { value: anime.stagger(-cell, { grid: grid, from: nextIndex, axis: 'x' }) },
translateY: { value: anime.stagger(-cell, { grid: grid, from: nextIndex, axis: 'y' }) },
scale: 1.5,
easing: 'cubicBezier(.075, .2, .165, 1)'
}, '-=800')
index = nextIndex;
}
play();
})();
</script>
</body>
</html>