PC端网页特效练习题
文章目录
重点
1.重点: 拖拽原理
2.重点: 缓动动画
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
注意: 多个目标之间缓速移动实现时候注意取整
从小数值移动到大数值, 每次移动的步长都向上取整, 否则最后会有一个小于10的差距;
比如0到10: style.left=0+10/10=1; 1+9/10=1.9; 1.9+8.1/10=2.71 … 始终无法精确到10
步长向上取整后: style.left=0+10/10=1; 1+|9/10|=2; 2+|8/10|=3; …可以精确到10
从大数值移动到小数值, 此时步长为负数, 步长向下取整!
一个封装好的animate.js就做好了:
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
//否则随着点击次数增加, 盒子移速会递增
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把步长值改为整数 不要出现小数的问题; 比如8.1取成9, 否则盒子会停在差几像素位置
// 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();
}
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
一, offset系列属性练习
1. 拖拽弹出框(模态框)
要求:
1.点击按钮弹出模态框, 并且显示灰色半透明遮挡层—display:block;
2.点击关闭, 关闭模态框, 并且同时关闭灰色遮挡层—display:none;
3.鼠标放到模态框最上一行(title是事件源)可以按住拖动—
4.鼠标松开停止拖动, 模态框停在原地—mouseup
第三步实现要点:mousedown,mousemove;获取鼠标在图形内相对位置, 鼠标绝对位置-相对位置=盒子左侧距页面距离
按住移动过程中, 按下鼠标一瞬间开始, 鼠标在盒子内的相对位置是不变的, 获取这个相对位置.
随后, 鼠标移动, 此时鼠标在页面内的位置改变, 要按照: 改变鼠标位置-获取盒子offsetLeft-赋新值给left和top
// 4. 开始拖拽
// (1) 当我们鼠标按下, 就获得鼠标在盒子内的坐标
title.addEventListener('mousedown', function(e) {
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
// (2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
document.addEventListener('mousemove', move)
//方便移除, 把函数拿出来取名
function move(e) {
login.style.left = e.pageX - x + 'px';
login.style.top = e.pageY - y + 'px';
}
// (3) 鼠标弹起,就让鼠标移动事件移除
document.addEventListener('mouseup', function() {
document.removeEventListener('mousemove', move); //移除须有函数名
})
})
3. 商品放大镜
二, scroll属性练习
1. 淘宝固定右侧侧边栏
a. 开始滚动时, 侧边栏随着用户一起滚动;—scroll事件的事件源是document
b. 当侧边栏滚动到最上方, 变为固定定位, 页面滚动而侧边栏不动;—并非scroll属性
c. 并且侧边栏中出现’前往顶部’选项;
注意区分window.pageYOffset和element.scrollTop
页面被卷去的头部: 通过window.pageYOffset获得, 被卷左侧通过window.pageXOffset;
元素被卷头部则通过element.scrollTop获得;
//还有注意O大写,我写成小写浪费好多时间改bug,难受
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 10 auto;
padding: 0;
}
.page {
float: left;
width: 100%;
height: 7500px;
background-color: pink;
}
button {
position: fixed;
display: block;
width: 100px;
height: 100px;
margin: 370px 680px;
background: red;
}
</style>
</head>
<body>
<div class="page">123
</div>
<button></button>
<script>
var button = document.querySelector('button');
button.onclick = function() {
windowScrollToTarget(0);
};
// 动画函数
function windowScrollToTarget(target, callback) {
var timer = setInterval(function() {
var step = (target - window.pageYOffset) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (window.pageYOffset == target) {
clearInterval(timer);
callback && callback();
}
var targetPositionY = window.pageYOffset + step;
window.scroll(0, targetPositionY);
}, 15);
}
</script>
</body>
</html>
三, 动画
1. 飘动的盒子们
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}
span {
position: absolute;
left: 0;
top: 200px;
display: block;
width: 150px;
height: 150px;
background-color: purple;
}
</style>
</head>
<body>
<button class="btn500">点击夏雨荷到500</button>
<button class="btn800">点击夏雨荷到800</button>
<span>夏雨荷</span>
<script>
// 缓动动画函数封装obj目标对象 target 目标位置
// 思路:
// 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
// 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
// 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
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();
}
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click', function() {
// 调用函数
animate(span, 500);
})
btn800.addEventListener('click', function() {
// 调用函数
animate(span, 800, function() {
// alert('你好吗');
span.style.backgroundColor = 'red';
});
})
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
</script>
</body>
</html>
2. 轮播图
参见淘宝网的core-slide制作
把上个案例的animate函数封装, 方便随时调用