javascript- PC端特效(一)
元素偏移量offset
动态的得到该元素的位置、大小等
- 获取元素距离带有定位的父元素的位置
- 获取元素自身的大小
<style> * { margin: 0; padding: 0; } .father { width: 200px; height: 200px; background-color: pink; margin: 100px; padding: 20px; } .son { width: 100px; height: 100px; background-color: blue; margin: 45px; } </style>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
//可以得到元素的偏移 位置 返回的不带单位的数值
console.log(father.offsetTop);
//它以带有定位的父亲为准 如果没有父亲或者父亲没有定位 则已body为准
console.log(son.offsetTop);
console.log(son.offsetLeft);
//可以得到元素的大小 宽度高度 包含padding+border+width
console.log(father.offsetWidth);
//3.返回带有定位的父亲,否认返回的body
console.log(son.offsetParent);//父亲必须带有定位才返回
console.log(son.parentNode);//返回父亲 最近一级的父亲
</script>
offset和style的区别
offset:
- 可以得到任意样式表中的样式值
- 获得的数值没有单位
- offsetWidth包含padding+border+width
- offsetWidth等属性是只读属性,只能获取不能赋值
所以我们想要获取元素大小位置,用offset更合适
style:
- 只能得到行内样式表中的样式值
- style.width获得的是带有单位的字符串
- style.width获得不包含padding和border值
- style.width是可读属性,可以获得也可以赋值
所以,我们想要给元素更改值,则需要用style
案例:获取位置
- 我们在盒子内点击,想要得到鼠标距离盒子左右的距离
- 首先得到鼠标在页面的坐标(e.pageX,e.pageY)
- 其次得到盒子在页面中的距离(box.offsetLeft,box.offsetTop)
- 用鼠标距离页面的坐标减去盒子在页面中的距离,得到鼠标在盒子内的坐标
案例:拖动的模块框
- 点击弹出层,模态框和遮挡层就会显示出来display:block;
- 点击关闭按钮,模态框和遮挡层就会隐藏起来display:none;
- 在页面中拖拽的原理:鼠标按下并且移动,之后松开鼠标
- 触发事件是鼠标mousedown,鼠标移动mousemove,鼠标松开mouseup
- 拖拽过程:鼠标移动过程中,获得最新的值赋值给模态框的left和top值,这样就可以跟着鼠标走了
- 鼠标按下触发的事件源是最上面的一行,就是id为title
- 鼠标的坐标减去鼠标在盒子内的坐标,才是模态框真正的位置
- 鼠标按下,我们要得到鼠标在盒子的坐标
- 鼠标移动,就让模态框的坐标设置为:鼠标坐标减去盒子坐标即可,注意移动事件写到按下事件里面。
- 鼠标松开,就停止拖拽,就是可以让鼠标移动事件解除
<style> .login-header { width: 100%; text-align: center; height: 30px; font-size: 24px; line-height: 30px; } ul, li, ol, dl, dt, dd, div, p, span, h1, h2, h3, h4, h5, h6, a { padding: 0px; margin: 0px; } .login { display: none; width: 512px; height: 280px; position: fixed; border: #ebebeb solid 1px; left: 50%; top: 50%; background: #ffffff; box-shadow: 0px 0px 20px #ddd; z-index: 9999; transform: translate(-50%, -50%); } .login-title { width: 100%; margin: 10px 0px 0px 0px; text-align: center; line-height: 40px; height: 40px; font-size: 18px; position: relative; cursor: move; } .login-input-content { margin-top: 20px; } .login-button { width: 50%; margin: 30px auto 0px auto; line-height: 40px; font-size: 14px; border: #ebebeb 1px solid; text-align: center; } .login-bg { display: none; width: 100%; height: 100%; position: fixed; top: 0px; left: 0px; background: rgba(0, 0, 0, .3); } a { text-decoration: none; color: #000000; } .login-button a { display: block; } .login-input input.list-input { float: left; line-height: 35px; height: 35px; width: 350px; border: #ebebeb 1px solid; text-indent: 5px; } .login-input { overflow: hidden; margin: 0px 0px 20px 0px; } .login-input label { float: left; width: 90px; padding-right: 10px; text-align: right; line-height: 35px; height: 35px; font-size: 14px; } .login-title span { position: absolute; font-size: 12px; right: -20px; top: -30px; background: #ffffff; border: #ebebeb solid 1px; width: 40px; height: 40px; border-radius: 20px; } </style>
<div class="login-header"><a id="link" href="javascript:;">点击,弹出登录框</a></div>
<div id="login" class="login">
<div id="title" class="login-title">登录会员
<span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<div class="login-input">
<label>登录密码:</label>
<input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
</div>
<!-- 遮盖层 -->
<div id="bg" class="login-bg"></div>
<script>
//1.获取元素
var login = document.querySelector('.login');
var mask = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var closeBtn = document.querySelector('#closeBtn');
var title = document.querySelector('#title');
//2.添加点击事件让mask和login显示出来
link.addEventListener('click', function () {
mask.style.display = 'block';
login.style.display = 'block';
});
//3.点击closeBtn就隐藏,mask和login
closeBtn.addEventListener('click', function () {
mask.style.display = 'none';
login.style.display = 'none';
});
//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)
})
});
</script>
元素的可视区client系列
<style> div { width: 100px; height: 100px; background-color: pink; border: 10px solid red; } </style> <div></div> <script> var div = document.querySelector('div'); console.log(div.clientWidth); </script>
立即执行函数(function(){})()
主要作用:创建一个独立的作用域
<script>
//立即执行函数:不需要调用,立马能够自己执行的函数
function fn() {
console.log(1);
}
fn();
//2.写法 也可以传递参数进去
(function (a, b) {
console.log(a + b);
})(3, 4); //第二个小括号可以看错是调用函数
((function sum(a, b) {
console.log(a + b);
})(2, 3))
//3.立即执行函数最大的作用就是独立创建一个作用域,里面里面的所有变量都是局部变量不会有命名冲突
</script>
scroll系列
使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离
<script>
var div = document.querySelector('div');
console.log(div.scrollHeight);
console.log(div.clientHeight);
//滚动事件当滚动条发生滚动触发事件
document.addEventListener('scroll', function () {
console.log(div.scrollTop);
});
</script>
案例:仿淘宝侧边栏
需要用到页面滚动事件scroll因为是页面滚动,所以事件源是document
滚动到某个位置,就是判断页面被卷去的上部值
页面被卷去的头部:可以通过window.pageYOffset获得 如果是被卷去的左侧 window.pageXOffset
注意,元素被卷去的头部是element.scroll Top
<script>
//1. 获取元素
var sliderbar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
// banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
var bannerTop = banner.offsetTop
// 当我们侧边栏固定定位之后应该变化的数值
var sliderbarTop = sliderbar.offsetTop - bannerTop;
// 获取main 主体元素
var main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var mainTop = main.offsetTop;
// 2. 页面滚动事件 scroll
document.addEventListener('scroll', function() {
// console.log(11);
// window.pageYOffset 页面被卷去的头部
// console.log(window.pageYOffset);
// 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位
if (window.pageYOffset >= bannerTop) {
sliderbar.style.position = 'fixed';
sliderbar.style.top = sliderbarTop + 'px';
} else {
sliderbar.style.position = 'absolute';
sliderbar.style.top = '300px';
}
// 4. 当我们页面滚动到main盒子,就显示 goback模块
if (window.pageYOffset >= mainTop) {
goBack.style.display = 'block';
} else {
goBack.style.display = 'none';
}
})
</script>
总结:

mouseenter和mouseover的区别
- 当鼠标移动到元素上时就会触发mouseenter事件
- 类似mouseover,它们两者之间的差别就是,mouseover鼠标经过自身的盒子会触发,经过子盒子也会触发。mouseenter只会经过自身盒子触发。
动画实现原理
核心原理:通过定时器setInterval()不断移动盒子位置
实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器
- 需要添加定位
<style> div { position: absolute; left: 0; width: 100px; height: 100px; background-color: pink; } </style> <div></div> <script> var div = document.querySelector('div'); var timer = setInterval(function () { if (div.offsetLeft >= 400) { //stop 本质停止定时器 clearInterval(timer); } div.style.left = div.offsetLeft + 1 + 'px'; }, 30); </script>
动画函数简单封装
传递两个参数 动画对象和移动的距离
<div></div>
<span>xiayuhe</span>
<script>
//目标对象,目标位置
function animate(obj, target) {
var timer = setInterval(function () {
if (obj.offsetLeft >= target) {
//stop 本质停止定时器
clearInterval(timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
// animate(div, 300);
animate(span, 200);
</script>
给不同元素记录不同的计时器
<div></div>
<span>夏雨荷</span>
<button>点击夏雨荷触发</button>
<script>
//目标对象,目标位置
function animate(obj, target) {
//当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
//解决方案,让我们的元素只有一个定时器执行
//先清除以前的定时器,只保留一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
if (obj.offsetLeft >= target) {
//stop 本质停止定时器
clearInterval(timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button');
animate(div, 300);
btn.addEventListener('click', function () {
animate(span, 200);
});
</script>
缓动动画效果
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
- 核心算法:(目标值-现在的位置)/10 作为每次移动的距离步长
- 停止条件是:让当前盒子位置等于目标位置就停止定时器
<div></div>
<span>夏雨荷</span>
<button>点击夏雨荷触发</button>
<script>
//目标对象,目标位置
function animate(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 10;
if (obj.offsetLeft == target) {
//stop 本质停止定时器
clearInterval(timer);
}
//把每次+1的步长值改为一个慢慢变小的值
obj.style.left = obj.offsetLeft + step + 'px';
}, 30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button');
animate(div, 300);
btn.addEventListener('click', function () {
animate(span, 200);
});
//匀速动画就是盒子当前的位置+固定的值10
//缓动动画就是盒子当前的位置+变化的值((目标值-现在的位置)/10)
</script>
动画函数多个目标值之间移动
可以让动画从800移动到500
判断是正值还是负值
1.如果是正值,则步长往大取整
2.如果是负值,则步长往小取整
<span>夏雨荷</span>
<button class="btn500">点击夏雨荷触发500</button>
<button class="btn800">点击夏雨荷触发800</button>
<script>
//目标对象,目标位置
function animate(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
//把步长改为整数
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
//stop 本质停止定时器
clearInterval(timer);
}
//把每次+1的步长值改为一个慢慢变小的值
obj.style.left = obj.offsetLeft + step + 'px';
}, 30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
animate(div, 300);
btn500.addEventListener('click', function () {
animate(span, 500);
});
btn800.addEventListener('click', function () {
animate(span, 800);
});
//匀速动画就是盒子当前的位置+固定的值10
//缓动动画就是盒子当前的位置+变化的值((目标值-现在的位置)/10)
</script>
动画函数添加回调函数
原理:函数可以作为一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。
动画函数封装到单独JS文件里
创建一个JS文件
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); }
返回顶部
滚动窗口至文档中的特定位置
Window.scroll(x,y)

浙公网安备 33010602011771号