1. 元素尺寸和定位获取方法
1.1 元素尺寸的获取
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/76ffd88a026a5d9cb255bf601ee05424.png#pic_center)
1.2 offset 系列属性
1.2.1 offset 作用
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/4328cc7b637778e8c11d759df8b1c2aa.png#pic_center)
1.2.2 offset 常用属性
-
offsetWidth
- 获取对象自身的
宽度
,包括内容、边框和内边距
,(不包括外边距)
offsetWidth = width + border + padding
-
offsetHeight
- 获取对象自身的
高度
,包括内容、边框和内边距
,(不包括外边距)
offsetHeight = height + border + padding
-
offsetLeft
- 距离
第一个有定位的父级盒子
左边的距离 父级盒子必须要有定位
,如果没有
,则最终以body
为准
-
offsetTop
- 距离
第一个有定位的父级盒子
上边的距离 父级盒子必须要有定位
,如果没有
,则最终以body
为准
-
offsetParent
- 返回
当前对象的父级(带有定位)盒子
,可能是父亲、也可能是爷爷
1.2.3 offset 系列属性使用说明
- offsetLeft 和 offsetTop 相关的父级
必须具有定位属性
- 祖先级
都有定位
时,以最近
的为基准 - 祖先级
都没有定位
时,以body
为基准
1.2.4 offset 系列属性和 style 的区别
- offset 系列属性和 style 属性
区别
offset
系列属性可以获取任何元素的边距
,style
只能获取具有定位元素的边距
offset
系列属性获取的是数字
,style
获取的除了数字,还有单位(px)
offset
系列属性只能读取不能赋值
,style
可以读写操作
offset
系列属性没有限制
,style
只能获取行内样式的边距
1.2.5 offsetParent 和 parentNode 区别
parentNode
parentNode
指与位置无关
的上级
元素parentNode
最多能获取到document
文档对象
offsetParent
offsetParent
指与位置有关
的上级
元素offsetParent
最多获取到body
元素,在往上获取就是null
1.2.6 offset 练习
<style>
*{margin: 0;padding: 0;}
ul{list-style: none;}
#header{
width: 400px;
margin: 10px auto;
position: relative;
}
span{
display: inline-block;
width: 80px;
height: 40px;
background: url(leaf.png);
position: absolute;
left: 0;
top: 0;
}
li{
width: 80px;
height: 40px;
text-align: center;
line-height: 40px;
float: left;
position: relative;
}
</style>
<script>
window.onload = function(){
var currentLeft = 0
var lis = document.getElementsByTagName('li');
var span = document.getElementsByTagName('span')[0];
var length = lis.length
for(var i = 0; i < length; i++) {
lis[i].onmouseover = function(){
span.style.left = this.offsetLeft + 'px'
}
lis[i].onclick = function(){
currentLeft = this.offsetLeft
}
lis[i].onmouseout = function(){
span.style.left = currentLeft + 'px'
}
}
}
</script>
<body>
<div id="header">
<span></span>
<ul>
<li>首页</li>
<li>热门商品</li>
<li>商品详情</li>
<li>购物车</li>
<li>论坛</li>
</ul>
</div>
</body>
1.3 scroll 系列属性
1.3.1 scroll 作用
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5fae59374cb18679a064d83bdee9486b.png#pic_center)
1.3.2 scroll 常用属性
scrollWidth
scrollHeight
scrollTop
scrollLeft
1.3.3 处理 scroll 家族浏览器适配问题
window.pageXOffset; (scrollLeft)
window.pageYOffset; (scrollTop)
document.documentElement.scrollTop;
Chrome浏览器 和 没有声明 DTD <DOCTYPE >
document.body.scrollTop;
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
1.3.4 scrollTo(x,y) 和 scrollBy(x,y) 方法
-
scrollTo(x,y)
- 把内容
滚动到指定的坐标
格式
scrollTo(xpos,ypos)
xpos
必需,要在窗口文档显示区左上角显示的文档的 x
坐标ypos
必需,要在窗口文档显示区左上角显示的文档的 y
坐标
- 网页大部分都
没有水平滚动条
,所以,这个 x 不太常用
-
scrollBy(x,y)
- 把内容滚动
指定的像素数
格式
scrollBy(xnum,ynum)
xnum
必需,把文档向右滚动
的像素数ynum
必需,把文档向下滚动
的像素数
- 要使此方法工作 window 滚动条的
可见属性
必须设置为true
1.3.5 scroll 系列属性的获取
<style media="screen">
#container {
width: 300px;
height: 300px;
border: 1px solid #ccc;
overflow: scroll;
}
#d1 {
width: 400px;
height: 500px;
background-color: #ff0;
}
</style>
<script type="text/javascript">
window.onload = function(){
var div = document.getElementById('d1');
var divContainer = document.getElementById('container')
console.log('scrollWidth:'+ div.scrollWidth)
divContainer.onscroll = function(){
console.log('子元素滚动位置:' + divContainer.scrollTop);
}
}
</script>
<body>
<div id="container">
<div id="d1"></div>
</div>
</body>
1.3.6 scroll 练习
<style>
*{margin: 0;padding: 0;}
#head{
width: 0;
height: 0;
background: url(../images/head.jpg);
margin: 0;
}
#nav{
width: 1530px;
height: 48px;
background: url(../images/nav.jpg);
margin: 0;
}
#content{
width: 1530px;
height: 2350px;
background: url(../images/main.jpg);
margin: 0 auto;
}
</style>
<script>
window.onscroll = function(){
var nav = document.getElementById('nav')
var top = document.documentElement.scrollTop
if (top >= 100) {
nav.style.position = 'fixed'
nav.style
}else{
}
}
</script>
<body>
<div id="head"></div>
<div id="nav"></div>
<div id="content"></div>
</body>
1.4 client 系列属性
1.4.1 client 作用
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9419fc10cb595530e15197b574dde180.png#pic_center)
1.4.2 client 常用属性
clientWidth
clientHeight
clientLeft
- 返回的是元素
左边框
的borderWidth
- 如果
不指定一个边框
或者不定位
该元素,其值就为0
clientTop
- 返回的是元素
上边框
的borderHeight
- 如果
不指定一个边框
或者不定位
该元素,其值就为0
1.5 pageX/pageY、screenX/screenY、clientX/clientY 区别
screenX/screenY
是以屏幕为基准
进行测量
pageX
和 pageY
是以当前文档(绝对定位)为基准
,不适用于IE6-8
clientX
和 clientY
是以当前可视区域为基准
,类似于固定定位
1.6 offset、client 和 scroll 区别
1.6.1 width 和 height 分析
- scrollHeight 和 scrollWidth 表示
元素实际尺寸(包含超出可视区域)
- offsetHeight 和 offsetWidth 表示元素
可视区域内尺寸,包括边框
- clientHeight 和 clientWidth 表示元素
可视区域内尺寸,不包括边框和滚动条
1.6.2 left 和 top 分析
- scrollLeft(Top) 表示子元素
移出容器的左(顶)边的距离
- offsetleft(Top) 表示子元素和带定位属性的
父级元素的左(顶)边距
- clientLeft(Top) 表示元素的
左(顶)边距
1.7 获取屏幕的可视区域
window.innerWidth, window.innerHeight
document.documentElement.clientWidth, document.documentElement.clientHeight
document.body.clientWidth, document.body.clientHeight
function client() {
if(window.innerWidth){
return{
width: window.innerWidth,
height: window.innerHeight
}
}else if(document.compatMode != 'CSS1Compat'){
return{
width: document.body.clientWidth,
height: document.body.clientHeight
}
}
return{
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
}
}
2. JavaScript 动画制作基础
2.1 JavaScript 动画概述
- Javascript 动画是指页面元素的外观样式发生
逐步变化
的过程 - Javascript 依靠
定时器
,对页面元素的样式进行修改
实现动画效果
2.2 JavaScript 动画类型
2.3 JavaScript 动画制作步骤
- 使用
定时器
进行定时控制
- 设置定时的
开始和终止条件
- 修改元素的
外观样式
var div = document.getElementById('d1')
setInterval(function(){
var left = parseInt(div.style.left)
div.style.left = (left + 10) + 'px'
}, 200);
2.4 JavaScript 动画制作中的 bug
动画不能停止
设置具体值时不能停止
到达边界值时还可以运动
重复点击加快动画执行速度
2.5 JavaScript 动画制作要点
开始时先关闭定时器
把运动和停止分开
动画速度的调整方式
- 通过
定时器的时间间隔
进行调整 - 通过
动画变化的步长
进行调整,推荐采用
var timer = null
function moveRight(){
var div = document.getElementById('d1')
clearInterval(timer)
timer = setInterval(function(){
if(div.offsetLeft == 800) {
clearInterval(timer)
} else {
div.style.left = (div.offsetLeft + 10) + 'px'
}
},100)
}
2.6 JavaScript 动画练习
<style>
*{margin: 0;padding: 0;}
div {float: left;}
#left {
width: 100px;
height: 200px;
background-color: #ff0;
margin-left: -100px;
position: relative;
}
#right {
width: 30px;
height: 80px;
background-color: #0f0;
margin-top: 60px;
position: absolute;
right: -30px;
}
</style>
<script>
var timer = null
var left,right
window.onload = function(){
left = document.getElementById('left')
right = document.getElementById('right')
left.onmouseover = function(){
toRight()
}
left.onmouseout = function(){
toLeft()
}
}
function toRight(){
clearInterval(timer)
timer = setInterval(function(){
var offsetLeft = left.offsetLeft
if(offsetLeft == 0){
clearInterval(timer)
} else {
left.style.marginLeft = (offsetLeft + 10) + 'px'
}
},100)
}
function toLeft(){
clearInterval(timer)
timer = setInterval(function(){
var offsetLeft = left.offsetLeft
if(offsetLeft == -100){
clearInterval(timer)
}else {
left.style.marginLeft = (offsetLeft - 10) + 'px'
}
},100)
}
</script>
<body>
<div id="left">
<div id="right">点我</div>
</div>
</body>
3. JavaScript 动画框架设计
3.1 匀速动画制作
- 通过
传参方式
实现动画代码的函数封装
- 传入
动画的对象
- 传入样式
修改后的终值target
- 传入
步长参数
function uniformAnimation(obj,target,step){
clearInterval(timer)
timer = setInterval(function(){
var offsetLeft = obj.offsetLeft
if(offsetLeft == target){
clearInterval(timer)
}else{
obj.style.marginLeft = (offsetLeft + step) + 'px'
}
},1000)
}
function uniformAnimation(obj,target){
var step
clearInterval(timer)
timer = setInterval(function(){
var offsetLeft = obj.offsetLeft
step = (target - offsetLeft) > 0 ? 10 : -10
if(offsetLeft == target){
clearInterval(timer)
}else{
obj.style.marginLeft = (offsetLeft + step) + 'px'
}
},1000)
}
3.1.1 匀速动画制作的优化
- 当
终止值无法相等
时采取接近原则
代替 - 利用
Math.abs 函数
进行数据的判断
function myAnimation1(obj, target){
var step
clearInterval(timer)
timer = setInterval(function(){
var offsetLeft = obj.offsetLeft
step = (target - offsetLeft) > 0 ? 7 : -7
if(Math.abs(offsetLeft - target) < 7){
clearInterval(timer)
obj.style.marginLeft = target + 'px'
} else {
obj.style.marginLeft = (offsetLeft + step) + 'px'
}
},100)
}
3.1.2 匀速淡入淡出动画练习
匀速淡入淡出动画框架
- 如何获取一个对象
当前的透明值
window.getComputedStyle(obj, null).opacity
function fadeAnimation(obj,target) {
var step
clearInterval(timer)
timer = setInterval(function(){
var opacity = parseFloat(window.getComputedStyle(obj,null).opacity)
step = (target - opacity) > 0 ? 0.1 : -0.1
if(opacity - target == 0){
clearInterval(timer)
}else{
obj.style.opacity = opacity + step
}
},100)
}
3.2 缓动动画制作
- 缓动动画是一种
逐渐变慢并最后停止
的动画 - 缓动动画的
速度由当前和终止两种状态的差值决定
速度计算公式
function slowAnimation(obj,target){
var step = 0
clearInterval(timer)
timer = setInterval(function(){
step = (target - obj.offsetLeft) / 10
if(target == obj.offsetLeft){
clearInterval(timer)
}else{
obj.style.left = (obj.offsetLeft + step) + 'px'
}
},100)
}
3.2.1 缓动动画存在的问题
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b62782c4e8865b3c5246bc84800bc22b.png#pic_center)
3.2.2 缓动动画解决精度问题
- 缓冲动画结束时的
精度处理
- 缓冲动画结束的条件是
终点重合
function slowAnimation(obj,target){
var step = 0
clearInterval(timer)
timer = setInterval(function(){
step = (target - obj.offsetLeft) / 10
step = step > 0 ? Math.ceil(step) : Math.floor(step)
if(target == obj.offsetLeft){
clearInterval(timer)
}else{
obj.style.left = parseFloat(obj.offsetLeft + step) + 'px'
}
},100)
}
3.2.3 缓动淡入淡出动画
function fadeSlowAnimation(obj, target){
var step = 0
clearInterval(timer)
timer = setInterval(function(){
var opacity = parseFloat(window.getComputedStyle(obj, null).opacity) * 100
step = (target - opacity) / 10
step = step > 0 ? Math.ceil(step):Math.floor(step)
if(target == opacity){
clearInterval(timer)
}else{
obj.style.opacity = (opacity + step) / 100
}
},100)
}
3.3 复合动画制作
- 复合动画是由
多个元素或多个属性
同时形成的动画 多个元素
动画存在的问题
多个属性
动画存在的问题
3.3.1 多元素动画
多个元素
动画解决方案
- 采用
多个定时器
- 定时器作为每个元素的
独立属性
公共属性
也作为每个元素的独立属性
function eleAnimation(obj, target){
var step = 0
clearInterval(obj.timer)
obj.timer = setInterval(function(){
step = (target - obj.offsetWidth) / 10
step = step > 0 ? Math.ceil(step) : Math.floor(step)
if(target == obj.offsetWidth){
clearInterval(obj.timer)
}else{
obj.style.width = (obj.offsetWidth + step) + 'px'
}
},100)
}
3.3.2 多属性动画
多个属性
动画解决方案
- 使用
属性作为框架的参数
,分别处理 - 使用
非行间样式
的获取方法
console.log(div.style.width)
console.log(div.style.height)
console.log(div.style['width'])
console.log(div.styel['height'])
function attrAnimation(obj, target, attribute){
var step = 0
clearInterval(obj.timer)
obj.timer = setInterval(function(){
step = (target - parseInt(obj.style[attribute])) / 10
step = step > 0 ? Math.ceil(step) : Math.floor(step)
if(target == parseInt(obj.style[attribute])){
clearInterval(obj.timer)
}else{
obj.style[attribute] = (parseInt(obj.style[attribute]) + step) + 'px'
}
},100)
}
3.4 链式动画制作
- 链式动画是指
按先后顺序执行的多个动画
- 工作原理
- 在框架函数中
添加一个动画函数作为参数
- 在前一个动画
清除定时器
后,调用参数提供的动画函数
function chainAnimation(obj, target, attribute, fn) {
var step = 0
clearInterval(obj.timer)
obj.timer = setInterval(function(){
step = (target - parseInt(obj.style[attribute])) / 10
step = step > 0 ? Math.ceil(step) : Math.floor(step)
if(target == parseInt(obj.style[attribute])){
clearInterval(obj.timer)
if(fn)
fn()
}else{
obj.style[attribute] = (parseInt(obj.style[attribute]) + step) + 'px'
}
},100)
}
3.5 动画制作小结
动画类型 | 动画框架结构 |
---|
基本型动画 | Animation(target) |
多元素动画 | Animation(obj, target) |
多类属性动画 | Animation(obj, attr, target) |
链式动画 | Animation(obj, attr, target, fn) |
4. 总结
- JavaScript 简单动画封装总结,以后有机会再完善一下动画框架