示例代码:我的github
demo效果演示示例:我的demo网站
效果:匀速运动
Document
匀速运动
使用定时器控制位置
效果:侧边栏效果
Document
拉开
效果:缓动运动
缓动运动就是通过控制速度,使动画达到淡出效果
Document
拉开
注意:
speed = (end - box.offsetLeft)/20;
代表用(终点位置-当前位置)/动画系数
动画系数可以控制动画的快慢
效果:透明度运动
通过修改透明度变化进而修改动画
Document
效果:多物体运动
Document
注意:多物体运动时,定时器需要绑在对象上,清除定时器时,只需要清除自己的定时器即可
效果:多值运动
将上述代码进一步封装,使其可以针对任意属性变化都能产生动画效果
Document
效果:链式运动
可以让物体先变宽再变长,只需要将上述代码加回调函数的参数即可
myAnimation.js
/**
* 动画函数
* @param {Object} obj 当前对象
* @param {Object} attr 当前元素对象的属性
* @param {Object} end 末尾位置
* @param {Object} fn 回调函数
* */
function startAnimation(obj,attr,end,fn) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
let cur = 0,speed = 0;
if(attr === 'opacity'){
cur = Math.round(parseFloat(getStyle(obj,attr)) * 100);
// console.log(getStyle(obj,attr));
}else{
cur = parseInt(getStyle(obj,attr));
}
if(end === cur){
clearInterval(obj.timer);
// 回调函数放在动画执行结束之后
if(fn){
fn();
}
return;
}
// 运动
speed = end > cur ? 10:-10;
if(attr === 'opacity'){
// console.log(cur + speed);
obj.style[attr] = (cur + speed) / 100;
obj.style['filter'] = `alpha(opacity:${cur + speed})`;
}else{
obj.style[attr] = cur + speed + 'px';
}
},30)
}
// 获取属性
function getStyle(obj,attr) {
if(obj.currentStyle){
// 针对IE浏览器
return obj.currentStyle[attr];
}else{
// 针对于Firefox浏览器
return getComputedStyle(obj,null)[attr];
}
}
index.html
Document
效果:同时运动
可以让物体同时变长变宽,修改原来代码,将传入的属性和值改成传入json格式类型
动画库最终版本
myAnimation2.js
/**
* 动画函数
* @param {Object} obj 当前对象
* @param {Object} json 当前元素属性列表
* @param {Object} fn 回调函数
* */
function startAnimation(obj,json,fn) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
let cur = 0,speed = 0;
let flag = true; // flag:代表所有动画执行完毕
// 将json中所有元素属性遍历,修改
for(attr in json){
let end = json[attr];
// 获取对象属性值
switch(attr){
case "opacity":
cur = Math.round(parseFloat(getStyle(obj,attr)) * 100);
break;
case "scrollTop":
cur = obj[attr];
break;
default:
cur = parseInt(getStyle(obj,attr));
}
// 临界处理 该动画没有执行完毕
if(end !== cur){
flag = false;
}else{
continue;
}
console.log(cur);
// 设置速度:判断结束值end和当前值cur相差值小于speed速度
if(end > cur){
// end=100 cur=92 speed=10
speed = end - cur < 100?end - cur:100;
}else{
// end=0 cur=2 speed=-10
speed = end - cur > -100?end - cur:-100;
}
// 设置值
switch(attr){
case "opacity":
obj.style[attr] = (cur + speed) / 100;
obj.style['filter'] = `alpha(opacity:${cur + speed})`;
break;
case "scrollTop":
obj[attr] = cur + speed;
break;
default:
obj.style[attr] = cur + speed + 'px';
}
}
// 查看flag是否为true, 都当所有属性都没有被修改时,flag为true,结束动画
if(flag){
clearInterval(obj.timer);
if(fn){
fn();
}
return ;
}
},30)
}
// 获取属性
function getStyle(obj,attr) {
if(obj.currentStyle){
// 针对IE浏览器
return obj.currentStyle[attr];
}else{
// 针对于Firefox浏览器
return getComputedStyle(obj,null)[attr];
}
}
使用for遍历json,将每个属性修改,直到最后,当每个属性都到最终值时,条件结束,清除定时器
index.html
Document
效果:关闭页脚广告效果
点击关闭按钮,右下角广告就会先向下移动再向右移动至消失,具体myAnimation2.js文件在上述有写到
点击前往myAnimation2.js文件内容
Document
效果:侧边栏横幅效果
左侧中间的广告随着页面移动,而一直向中间移动的动画
点击前往myAnimation2.js文件内容
Document
offsetTop 偏移量,相当于绝对定位的子盒子的top属性
docScroll 使用兼容性写法,因为获取滚动高度可能由于浏览器不同获取方法不同
效果:淘宝侧边导航效果
右侧侧边导航,随着页面移动,导航条上也移动到相应栏目;如果点击导航条上板块名,页面也会移动到相应板块处
点击前往myAnimation2.js文件内容
Document
爱逛好货
好店直播
品质特色
实惠热卖
[…Divs] 使用了es6写法,将dom获取的集合类型转换为真正的数组,有forEach变量方法;这一步等价于使用for(element in Divs)
循环
效果:轮播图
可以自动滚动,鼠标悬停时,取消滚动;可以上一页下一页,可以点击索引跳到相应位置
点击前往myAnimation2.js文件内容
index.html
Document
index.css
*{
padding: 0;
margin: 0;
}
.slider{
width: 400px;
height: 500px;
margin: 100px auto;
position: relative;
overflow: hidden;
}
.slider_scroll {
position: relative;
width: 400px;
height: 500px;
}
.slider_main{
position: relative;
width: 400px;
height: 500px;
}
.slider_main .item{
width: 40px;
height: 500px;
position: absolute;
}
.slider_main .item img{
width: 400px;
height: 500px;
}
/* 索引部分 */
.slider_index{
width: 400px;
height: 40px;
line-height: 40px;
text-align: center;
color:#fff;
font-weight: 700;
z-index: 20;
position: absolute;
bottom: 0;
background-color: rgba(0,0,0,.5);
}
.slider_index .slider_index_icon{
margin: 0 10px;
line-height: 40px;
cursor: pointer;
}
.slider_index .slider_index_icon.current{
color: red;
}
/* 下一张和上一张定位 */
.slider_scroll>span{
position: absolute;
width: 30px;
height: 68px;
background: url(../images/icon-slides.png) no-repeat;
top: 50%;
margin-top: -34px;
cursor: pointer;
}
.slider_scroll span.next{
right: 0;
background-position: -46px 0;
}
.slider_scroll span.prev{
left: 0;
background-position: 0 0;
}
index.js
window.onload = function () {
// 获取元素
const slider = document.getElementById("slider");
const slider_main = document.getElementById("slider_main");
const slider_items = slider_main.children;
const next = document.getElementById("next");
const prev = document.getElementById("prev");
const slider_index = document.getElementById("slider_index");
let iNode = 0; //当前显示索引的坐标
// 动态创建索引
[...slider_items].forEach((v,i)=>{
let span = document.createElement("span");
span.innerText = i+1;
// 给索引添加类
if(i === 0){
span.className = "slider_index_icon current"
}else{
span.className = "slider_index_icon"
}
slider_index.appendChild(span);
})
// 让滚动元素归位
let scroll_w = this.parseInt(getStyle(slider,'width'));
// console.log(scroll_w);
[...slider_items].forEach((item,i,arr)=>{
if(i !== 0){
item.style.left = scroll_w + "px";
}
});
// 下一步按钮
function autoPlay() {
// 1.将显示的图片向左移动
startAnimation(slider_items[iNode],{
"left":-scroll_w
});
// 将下一张图片放在中心盒子的右边
iNode++;
if(iNode >= slider_items.length){
iNode = 0;
}
// console.log(slider_items[iNode].left);
slider_items[iNode].style.left = scroll_w + "px";
// console.log(slider_items[iNode].left);
// 将下一张图片向左移动
startAnimation(slider_items[iNode],{
"left":0
});
updateIndex();
}
next.onclick = autoPlay;
// 更新索引样式
let slider_index_items = slider_index.children;
function updateIndex() {
// console.log(slider_index_items);
[...slider_index_items].forEach((item,i)=>{
if(i == iNode){
item.className = "slider_index_icon current";
}else{
item.className = "slider_index_icon"
}
})
}
// 上一步按钮
prev.onclick = function () {
// 1.将该元素右移动
startAnimation(slider_items[iNode],{
"left":scroll_w
})
// 2.将上一个元素放在左边
iNode--;
if(iNode < 0){
iNode += slider_items.length
}
slider_items[iNode].style.left = -scroll_w + "px";
// 3.将上一个元素右移
startAnimation(slider_items[iNode],{
"left":0
})
// 更新下面索引
updateIndex();
};
// 设置索引点击事件
[...slider_index_items].forEach((item,i)=> {
item.onmousedown = function () {
// 1.判断点击的索引与当前索引关系
if(iNode > i){ // 上一张图片效果
startAnimation(slider_items[iNode],{
"left":scroll_w
})
slider_items[i].style.left = -scroll_w + "px";
}else if(iNode < i){ // 下一张图片效果
startAnimation(slider_items[iNode],{
"left":-scroll_w
})
slider_items[i].style.left = scroll_w + "px";
}
iNode = i;
startAnimation(slider_items[iNode],{
"left":0
})
updateIndex();
}
});;
// 设置自动播放
let timer = window.setInterval(autoPlay,2000);
// 设置鼠标悬浮停止定时器,离开开启定时器
slider.onmouseover = function () {
clearInterval(timer);
}
slider.onmouseout = function () {
timer = window.setInterval(autoPlay,2000);
}
}
图片部分,在上传到github上面时,已经将素材上传上去了。