var oDiv = document.querySelector('div');
var oBtn = document.querySelector('button');
// left,top,opacity,宽,高 都改变
oBtn.addEventListener('click', function () {
move(oDiv, { left: 600, top: 600 , width:200 , height:400 , opacity:0}, function(){
console.log('运动结束了');
})
});
// 说明:
// 第一,需要使用ES6语法中的 let 声明变量
// 第二,如果是透明度,因为是小数,需要单独处理
// 第三,建立对象,存储定时器
// 第四,清除定时器器,同时删除对象中的单元
// 第五,判断对象,如果是一个空对象,证明所有运动都停止了
function move(ele, obj, callback) {
let time = {};
for (let type in obj) {
let oldVal = 0;
if (type === 'opacity') {
oldVal = parseFloat(window.getComputedStyle(ele)[type]) * 100;
} else {
oldVal = parseInt(window.getComputedStyle(ele)[type]);
}
time[type] = setInterval(function () {
let val = (obj[type] - oldVal) / 10;
val = val > 0 ? Math.ceil(val) : Math.floor(val);
oldVal += val;
if (type === 'opacity') {
ele.style[type] = oldVal / 100;
} else {
ele.style[type] = oldVal + 'px';
}
if (oldVal == obj[type]) {
clearInterval(time[type]);
delete (time[type]);
}
if (Object.keys(time) == 0) {
callback();
}
}, 100)
}
}
<style>
*{
margin: 0;
padding: 0;
}
div{
width: 100px;
height: 100px;
background: pink;
position: fixed;
top: 100px;
left: 0px;
}
</style>
</head>
<body>
<button>点击</button>
<div></div>
<script>
// 运动函数
// 轮播图中,图片的切换,不是瞬间切换完成的
// 而是以类似于动画/运动的方式,逐步切换完成
// 将位移/定位效果,分多次,逐步完成
// transition 虽然可以实现类似的效果
// 但是对于复杂的运动,复杂的设定,是不方便支持的
// 而且,transition过渡的兼容性,有待提高
// 通过JavaScript,配合 定时器 来逐步完成 运动效果
var oBtn = document.querySelector('button');
var oDiv = document.querySelector('div');
oBtn.addEventListener('click' , function(){
// 定义的初始值
var speed = 0;
// 定时器
var time = setInterval(function(){
// 每次初始值,增加一个数值
speed += 10;
// 将这个数值定义为定位的数值
oDiv.style.left = speed + 'px';
// 当数值达到规定的数值时,清除定时器,终止执行
// 运动也就终止了
if(speed == 500){
clearInterval(time);
}
} , 30)
})
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 100px;
height: 100px;
background: pink;
position: fixed;
top: 100px;
left: 200px;
transition: all 3s;
}
</style>
</head>
<body>
<button>点击</button>
<div></div>
<script>
// 解决第一个问题
// 封装成一个函数的形式
// 如果有初始位置,怎么办?
// 参数1,要运动的标签
// 参数2,要运动的方向/方式 以及 目标位置
// 一般,目标位置与运动方式是相关的,定义对象的形式
// { 方式 : 位置 } {left : 500}
// 获取标签对象
var oDiv = document.querySelector('div');
var oBtn = document.querySelector('button');
// 不愿意写点击事件,直接执行也可以
// move(oDiv,{left:500});
// 执行函数
// 给按钮绑定点击事件
// 执行的函数,是调用move()函数,并且赋值参数
// 注意:不能在 addEventListener 参数2的位置上,直接定义move(),这样会直接调用,此时需要的是绑定,等待触发条件然后执行
oBtn.addEventListener('click', function(){ move(oDiv,{left:500}) });
// 直接写move函数,是直接调用move函数,不是绑定move函数
// oBtn.addEventListener('click', move() );
function move(ele, obj) {
// 先通过for...in循环,来调用参数2,获取其中的执行属性和目标位置的数值
// 目前是有obj中,有一个单元,会循环一次,生成left对应的定时器
// 如果有obj中,有多个单元,会循环多次,生成每一个属性对应的定时器
// 这样,每一个属性都有自己对应的定时器,便于控制和观察运动状态
// type中存储的是,obj对象的键名,也就是left
for(var type in obj) {
// 初始位置,需要获取标签原始定位的数值
// 参数2中,定义的运动属性,是谁,现在对应的就获取谁的初始数值
// {left:500},就获取left属性对应的初始值
// window.getComputedStyle 获取标签的css样式的属性值,带有px
// 语法: window.getComputedStyle(标签对象).属性
// 这里的属性是存储在type自定义变量中的,必须要用[]语法来解析
var speed = parseInt(window.getComputedStyle(ele)[type]) ;
// 定时器,每次循环都会生成一个新的定时器
var time = setInterval(function(){
// 初始值,加上数值
speed += 20;
// 将数值作为定位的数据
// 点语法,不能解析变量,必须使用[]语法,解析存储的变量
// 设定 标签 css , 语法是 标签对象.style[属性] = 属性值
// type是for...in循环中,自定义的变量,用来存储对象的键名
// 要使用时,type是变量, 对象.变量,不能解析,只能使用对象[变量]才能解析变量
ele.style[type] = speed + 'px';
// 当数值,达到目标值的时候,来停止定时器
// obj是参数2,{left:500}
// 这个500使我们的目标数值
// 获取500这个数值,语法是 对象[属性]
// 属性存储在变量type中,必须要[]语法才能及解析
if (speed == obj[type]) {
clearInterval(time);
}
}, 100);
}
}
var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
var oH1 = document.querySelector('h1');
var oBtn1 = document.querySelectorAll('button')[0];
var oBtn2 = document.querySelectorAll('button')[1];
var oBtn3 = document.querySelectorAll('button')[2];
oBtn1.addEventListener('click' , function(){
move(oDiv,400 , 'left');
})
oBtn2.addEventListener('click' , function(){
move(oP,300 , 'top');
})
oBtn3.addEventListener('click' , function(){
move(oH1, 500 , 'left');
})
// 为了方便多次执行运动程序效果,将程序封装为函数
// 每次调用函数,操作的标签对象,可能是不同的标签对象
// 此时需要一个参数,来告诉函数,操作的标签对象谁
// 参数1:需要操作的,运动的标签对象
// 参数2:目标位置
// 参数3:运动方式
// 问题是: 1,参数的顺序,不可控制
// 2,参数的个数,不可控制
// 将参数2和参数3,写成对象的形式
// 也就是将 运动方式 和 目标位置 写成 对象的 属性:属性值 形式
function move(ele , target , type ){
var speed = 0;
var time = setInterval( function(){
speed += 20;
// 对象,调用变量,必须是[]语法来解析变量
ele.style[type] = speed + 'px';
if(speed == target){
clearInterval(time);
}
} , 100)
}
var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
var oH1 = document.querySelector('h1');
var oBtn1 = document.querySelectorAll('button')[0];
var oBtn2 = document.querySelectorAll('button')[1];
var oBtn3 = document.querySelectorAll('button')[2];
oBtn1.addEventListener('click' , function(){
move(oDiv, {left:600} );
})
oBtn2.addEventListener('click' , function(){
move(oP, {top:600});
})
oBtn3.addEventListener('click' , function(){
move(oH1, {left:600} );
})
// 参数1:执行运动的标签对象
// 参数2:执行运动的方式和目标位置,对象的形式
function move(ele , obj ){
// 获取对象中的属性和属性值,必须使用for...in来循环
// 语法 for(var 变量 in 对象){程序}
// 自定义变量中,存储的是对象的属性 对象[自定义变量]获取的就是属性值
// type就是 top left 属性 obj[type] 就是 500 600 属性值
for(var type in obj){
// 运动属性,对应的初始值
// 参数中的运动属性是谁,是top,还是left
// 也就是 type 中 存储是什么运动属性
// 我们就获取哪个运动属性的初始值
// 获取的方式,是通过获取标签css样式属性的属性值
// 应该是写成兼容的方式,暂时直接获取
// 语法 : window.getComputedStyle(标签对象).属性
// 1,标签对象,现在是形参ele,执行时赋值实参 oDiv,oP,oH1....
// 2, 属性,是存储在 type 形参变量中 的数据
// 必须使用[]语法,解析type变量
// window.getComputedStyle(ele)[type]
// 标签对象.style 只能获取行内样式
// window.getComputedStyle 获取的是最终执行的样式,不区分行内,内部,外部
// 只要是执行的,就能拿到手
// 执行结果有 px 单位 是 字符串形式 100px 200px ...
// 需要获取数值部分,也就是整数部分 parseInt() 来获取
var oldVal = parseInt(window.getComputedStyle(ele)[type]) ;
var time = setInterval( function(){
// 在原始数据的基础上,来执行运动
oldVal += 20;
// 对象,调用变量,必须是[]语法来解析变量
ele.style[type] = oldVal + 'px';
if( oldVal == obj[type] ){
clearInterval(time);
}
} , 100)
}
}
var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
var oH1 = document.querySelector('h1');
var oBtn1 = document.querySelectorAll('button')[0];
var oBtn2 = document.querySelectorAll('button')[1];
var oBtn3 = document.querySelectorAll('button')[2];
oBtn1.addEventListener('click' , function(){
move(oDiv, {left:205} );
})
oBtn2.addEventListener('click' , function(){
move(oP, {top:9});
})
oBtn3.addEventListener('click' , function(){
move(oH1, {left:7} );
})
// 参数1:执行运动的标签对象
// 参数2:执行运动的方式和目标位置,对象的形式
function move(ele , obj ){
for(var type in obj){
// 获取原始位置
var oldVal = parseInt(window.getComputedStyle(ele)[type]) ;
// 定时器
var time = setInterval( function(){
// 计算需要改变的数值,是多少
// 目标位置 - 初始位置
// 向右向下移动,就是正数,向左向上移动就是负数
// 设定分几次完成改变数值,也就是定义每次改变的数值数值
// 根据 终止位置,起始位置,和执行次数,计算出每次需要改变的数值
var val = ( obj[type] - oldVal ) / 5 ;
// 如果执行结果是小数,需要做取整操作
// 通过三元运算符,给val变量进行赋值
// 当 val > 0 时 执行的是 Math.ceil(val) 向上取整
// 当 val <= 0 时 执行的是 Math.floor(val) 向下取整
// 正数,当数值 0.几 时 向上取整 变的数值 是 1
// 负数,当数值 -0.几 时 向下取整 变的数值 是 -1
// 确保每次改变的数值,最小是1
// 确定可以到达 目标位置,可以清除定时器
val = val > 0 ? Math.ceil(val) : Math.floor(val) ;
console.log(val)
// 每次改变的是计算出来的数值
oldVal += val;
// console.log(oldVal);
ele.style[type] = oldVal + 'px';
if( oldVal == obj[type] ){
clearInterval(time);
}
} , 100)
}
}
// 解决的问题:
// 监听中的参数三:运动结束之后的执行操作
var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
var oH1 = document.querySelector('h1');
var oBtn1 = document.querySelectorAll('button')[0];
var oBtn2 = document.querySelectorAll('button')[1];
var oBtn3 = document.querySelectorAll('button')[2];
oBtn1.addEventListener('click' , function(){
// 参数3,直接赋值函数
move(oDiv, {left:205} , function(){console.log('div停止了')} );
})
oBtn2.addEventListener('click' , function(){
// 参数3,直接赋值函数名称
move(oP, {top:9} , fff );
})
oBtn3.addEventListener('click' , function(){
move(oH1, {left:7} ,callback );
})
/* oBtn3.addEventListener('click' , function(){
move(oH1, {left:7} ); → 正常运动 但是运动停止后会在控制台中报错
}) */
// 参数1:执行运动的标签对象
// 参数2:执行运动的方式和目标位置,对象的形式
// 新增参数3:当运动停止时,执行的函数
// 这里的 callback 是形参
// 赋值的 实参,是函数的名称,或者变量名称,存储的都是函数的内存地址
// 必须要 通过() 来调用 赋值的函数 callback()
function move(ele , obj , callback ){
for(var type in obj){
// 获取原始位置
var oldVal = parseInt(window.getComputedStyle(ele)[type]) ;
// 定时器
var time = setInterval( function(){
// 获取需要改变数值,并且计算步长
var val = ( obj[type] - oldVal ) / 5 ;
// 取整,如果是正数,向上取整,如果是负数,向下取整
// 确保,最后每次改变的最小值是1
val = val > 0 ? Math.ceil(val) : Math.floor(val) ;
// 每次改变的是计算出来的数值
oldVal += val;
// 将改变后的数值,作为属性值,赋值给css样式,实现位置的改变
ele.style[type] = oldVal + 'px';
// 判断,如果当前位置,也就是改变后,数值是目标位置
if( oldVal == obj[type] ){
// 清除定时器,终止定时器的执行,运动停止
clearInterval(time);
// 当清除了定时器,也就是运动终止了
// 来调用参数3赋值的函数
callback();
}
} , 100)
}
}
function fff(){
console.log('不管你是谁,反正你的运动停止了');
}
function callback(){
console.log('不管你是谁,反正你的运动停止了');
}