1.0 缓动动画原理
思路:
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
- 核心算法: (目标值 - 现在的位置) / 10 做为每次移动的距离步长
- 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
- 步长值需要取整
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}//ping写的
匀速动画 就是: 盒子是当前的位置 + 固定的值 10
缓动动画就是: 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
步长公式:(目标值 - 现在的位置) / 10
2.0 轮播图
<div class="main">
<div class="focus fl">
<!-- 左侧按钮 -->
<a href="javascript:;" class="arrow-l">
<
</a>
<!-- 右侧按钮 -->
<a href="javascript:;" class="arrow-r"> > </a>
<!-- 核心的滚动区域 -->
<ul>
<li>
<a href="#"><img src="images/focus.jpg""></a>
</li>
<li>
<a href=" #"><img src="images/focus1.jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="images/focus2.jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="images/focus3.jpg" alt=""></a>
</li>
</ul>
<!-- 小圆圈 -->
<ol class=" circle">
</ol>
</div>
</div>
<script>
window.addEventListener('load', function () {
var zuo = document.querySelector('.arrow-l'); //左箭头
var you = document.querySelector('.arrow-r'); //右箭头
var box = document.querySelector('.focus'); //轮播图盒子
var boxWidth = box.offsetWidth; //图片的宽度
box.addEventListener('mouseover', function () { //鼠标经过显示
zuo.style.display = 'block';
you.style.display = 'block';
clearInterval(timer);
timer = null //清除定时器
})
box.addEventListener('mouseout', function () { //鼠标离开隐藏
zuo.style.display = 'none';
you.style.display = 'none';
timer = setInterval(function () { //开启定时器
you.click();
}, 2000)
})
var ul = box.querySelector('ul');
var ol = box.querySelector('.circle');
for (var i = 0; i < ul.children.length; i++) { //动态生成li 多少图片多少li
var li = document.createElement('li');
li.setAttribute('index', i) //设置索引号
ol.appendChild(li);
li.addEventListener('click', function () { //小圆点添加点击事件
for (var i = 0; i < ol.children.length; i++) { //排他思想,干掉别人留下自己
ol.children[i].className = '';
}
this.className = 'current';
//点击小圆圈 让ul 动起来 (移动图片)
var index = this.getAttribute('index'); //获取索引号
num = index; //点击了某个小li吧索引给num'
cir = index; //点击了某个小li吧索引给cir
animate(ul, -index * boxWidth);
})
}
ol.children[0].className = 'current'; //ol的第一个孩子为白色
ul.appendChild(ul.children[0].cloneNode(true)); //克隆的li放到ul的后面
//点击you按钮 图片滚动
var num = 0;
var cir = 0; //控制小圆圈的播放
var flag = true; //节流阀
you.addEventListener('click', function () {
if (flag) {
flag = false; //关闭节流阀
if (num == ul.children.length - 1) { //无缝滚动,当图片走到最后一张ul快速回到ul初始位置0
ul.style.left = 0 + 'px';
num = 0; //然后重新自加
}
num++;
animate(ul, -num * boxWidth, function () {
flag = true;
});
cir++; //控制小圆圈的播放
if (cir >= ul.children.length - 1) { //克隆的图片走到这步就清零
cir = 0
}
//清除小圆圈类名 留下当前个
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[cir].className = 'current';
}
})
zuo.addEventListener('click', function () {
if (flag) {
flag = false;
if (num == 0) { //无缝滚动,当图片走到最后一张ul快速回到ul初始位置0
num = ul.children.length - 1; //然后重新自加
ul.style.left = -num * boxWidth + 'px';
}
num--;
animate(ul, -num * boxWidth, function () {
flag = true;
});
cir--; //控制小圆圈的播放
if (cir < 0) { //克隆的图片走到这步就清零
cir = ol.children.length - 1;
}
//清除小圆圈类名 留下当前个
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
ol.children[cir].className = 'current';
}
})
//自动播放
var timer = setInterval(function () {
you.click();
}, 2000)
})
</script>
3.0 触屏事件
- 手指开始触摸到手机屏幕的时候 触发 一个 touchstart事件
- 手指在屏幕上移动的时候 触发一个 touchmove事件
- 手指离开屏幕那一刻 触发的事件 touchend事件
触摸事件对象 - 1、changedtouches 改变状态
- 2、targettouches 当前元素对象 的手指触摸个数
- 3、touches 触摸屏幕的时候手指的个数 | 触屏touch事件 | 说明 | | —- | —- | | touchstart | 手指开始触摸到手机屏幕的时候 触发一个 | | touchmove | 手指在屏幕上移动的时候 触发 | | touchend | 手指离开的那一刻触发 |
4.0 案例:移动端拖动元素
- touchstart、touchmove、touchend可以实现拖动元素
- 但是拖动元素需要当前手指的坐标值 我们可以使用 targetTouches[0] 里面的pageX 和 pageY
- 移动端拖动的原理: 手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离
- 手指移动的距离: 手指滑动中的位置 减去 手指刚开始触摸的位置
拖动元素三步曲:
(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
(3) 离开手指 touchend:
注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();
<script>
// (1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
// (2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
// (3) 离开手指 touchend:
var div = document.querySelector('div');
var startX = 0; //获取手指初始坐标
var startY = 0;
var x = 0; //获得盒子原来的位置
var y = 0;
div.addEventListener('touchstart', function(e) {
// 获取手指初始坐标
startX = e.targetTouches[0].pageX;
startY = e.targetTouches[0].pageY;
x = this.offsetLeft;
y = this.offsetTop;
});
div.addEventListener('touchmove', function(e) {
// 计算手指的移动距离: 手指移动之后的坐标减去手指初始的坐标
var moveX = e.targetTouches[0].pageX - startX;
var moveY = e.targetTouches[0].pageY - startY;
// 移动我们的盒子 盒子原来的位置 + 手指移动的距离
this.style.left = x + moveX + 'px';
this.style.top = y + moveY + 'px';
e.preventDefault(); // 阻止屏幕滚动的默认行为
//如果不阻止,当粉色盒子滚出界面之后会出现滚动条
});
</script>//pink写的