当前位置: 首页 > news >正文

webAPI中的offset、client、scroll

一、元素偏移量offset

1.offset概述

offset翻译成中文叫:偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等等

  • 获得元素距离带有定位父元素的位置
  • 获得元素自身的大小(宽度和高度)
  • 返回的数值都是不带单位的
offset的属性值说明
element.offsetParent返回作为该元素带有定位的父级元素,如果父级元素没有定位则返回body
element.offsetTop返回元素相对带有定位父元素上方的偏移
element.offsetLeft返回元素 相对带有定位父元素左边框的偏移
element.offsetWith返回自身包括padding、边框、内容区宽度,返回值不带单位
element.offsetHeight返回自身包括padding、边框、内容区高度,返回值不带单位
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>01offset系列属性</title><style>*{margin: 0;padding: 0;}.fahter{/* position: relative; */width: 200px;height: 200px;background-color: pink;margin: 150px;}.son{width: 100px;height: 100px;background-color: purple;margin-left: 45px;}.w{height: 200px;background-color: skyblue;/* margin: 0 auto 200px; */padding: 10px;border: 15px solid red;}</style>
</head>
<body><div class="fahter"><div class="son"></div></div><div class="w"></div><script>//offset系列属性var fahter = document.querySelector('.fahter');var son = document.querySelector('.son');var w = document.querySelector('.w');// 1.可以得到元素的偏移位置(返回的是不带单位的数值)console.log(fahter.offsetTop); //150console.log(fahter.offsetLeft); //150// 它以带有定位的父元素为准,如果没有父元素或者父元素没有定位,则以body为准console.log(son.offsetLeft);  console.log(son.offsetTop);//2.可以得到元素的大小的  宽度和高度:  包含了padding + border + widthconsole.log(w.offsetHeight);console.log(w.offsetWidth);//3.返回带有定位的父元素,否则返回的是bodyconsole.log(son.offsetParent);//返回的是带有定位的父元素,否则就返回bodyconsole.log(son.parentNode); //返回父元素,是最近一级的父元素,不管父元素是否有定位</script>
</body>
</html>

2.offset和style区别

offset

  • offset可以得到任意样式表中的样式值
  • offset系列获得的数值没有单位
  • offsetWidth包含padding+border+width
  • offsetWidth等等属性是只读属性,只能获取不能赋值

我们想要获取元素大小位置,我们用offset更合适

style

  • style 只能得到行内样式表中的样式值
  • style.width获得是带有单位的字符串
  • style.width获得不包含padding和border的值
  • style.width是可读可写属性,可以获取也可以赋值

我们想要给元素赋值或修改值,则需要用style改变

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>02offset和style的区别</title><style>.box{width: 200px;height: 200px;background-color: pink;padding: 10px;}</style>
</head>
<body><!-- 此处要写行内样式,否则 style.width将无法获取--><div class="box" style="width: 200px;"></div><script>var box = document.querySelector('.box');console.log(box.offsetWidth); //220console.log(box.style.width); //200px  只能获取行内样式// box.style.width = '300px' //可以重新赋值box.offsetWidth = '300px'  //offset是一个只读属性,无法重新赋值</script>
</body>
</html>

3.案例:计算鼠标在盒子中的坐标

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>03计算鼠标在盒子中的位置.html</title><style>.box{width: 300px;height: 300px;background-color: pink;margin: 200px;}</style>
</head>
<body><div class="box"></div><script>//我们在盒子里点击,得到位置var box = document.querySelector('.box');box.addEventListener('click',function(e){// var x = e.pageX;// var y = e.pageY;// console.log('x-->' + x + ',y--->' + y);// console.log(box.offsetLeft);//鼠标的位置var x = e.pageX - this.offsetLeft;var y = e.pageY - this.offsetTop;console.log('x-->' + x + ',y--->' + y);});</script>
</body>
</html>

4.模态框拖拽

需求:

  • 点击弹出层,会弹出模态框,并且显示灰色半透明遮挡层
  • 点击关闭按钮,可以关闭模态框,并且同时关闭灰色半透明遮挡曾
  • 鼠标放在模态框上面的一行,可以按住鼠标拖拽模态框在页面中移动
  • 鼠标松开,可以停止拖动模态框移动

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>模态框拖拽</title><style>*{margin: 0; padding: 0;}.login-header{width: 1000px;text-align: center;height: 30px;line-height: 30px;font-size: 24px;}a {color: #333;text-decoration: none;}.login{display: none;width: 512px;height: 280px;position: fixed;left: 50%;top:50%;background-color: #fff;box-shadow: 0px 0px 20px #ddd;transform: translate(-50%,-50%); /*以自身位置为准移动*/z-index: 10;}.login-title{width: 100%;margin: 10px 0px 0px 0px;text-align: center;line-height: 40px;height: 40px;font-size: 18px;cursor: move; /*鼠标形状*/position: relative;}.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;height: 100%;width: 100%;position: fixed;top: 0;padding: 0;background-color: rgba(0,0,0,.3);}.login-button a{display: block;clear: both;}.login-input {float: left;line-height: 35px;height: 35px;width: 350px;border: #ebebeb 1px solid;text-indent: 5px;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-color: #fff;border: #ebebeb solid 1px;width: 40px;height: 40px;border-radius: 20px;}</style>
</head>
<body><div class="login-header"><a href="javaScript:;" id="link">点击,弹出登录框</a></div><div id="login" class="login"><div id="title" class="login-title">会员登录<span><a href="javaScript:;" id="closeBtn" class="close-login">关闭</a></span></div><div class="login-input-content"><div class="login-input"><label for="">用户名:</label><input type="text" placeholder="请输入用户名"></div><div class="login-input"><label for="">登录密码:</label><input type="password" placeholder="请输入密码"></div><div id="loginBtn" class="login-button"><a href="javaScript:;">登录会员</a></div></div></div><!-- 遮盖层 --><div id="bg" class="login-bg"></div><script>//1.获取元素var login = document.getElementById('login'); //登录模态框var mask = document.getElementById('bg');	//遮挡层var closeBtn = document.getElementById('closeBtn'); //关闭按钮var title = document.getElementById('title'); //要拖着这个动var link = document.getElementById('link');	//点击后弹出模态框的链接//2.点击弹出登录link.addEventListener('click',function(){mask.style.display = 'block';login.style.display = 'block'});//3.点击closeBtn隐藏mask和logincloseBtn.addEventListener('click',function(){mask.style.display = 'none'  //遮挡层login.style.display = 'none' //登录模态框});//4.开始拖拽title.addEventListener('mousedown',function(e){//1)获取鼠标的位置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>
</body>
</html>

5.案例:京东放大镜

分析:

  • 黄色的遮挡层跟随鼠标移动
  • 把鼠标坐标给遮挡层不合适,因为遮挡层坐标以父盒子为准
  • 首先获取鼠标在盒子中的坐标
  • 之后再把数值给遮挡层作为left和top的值
  • 此时用到鼠标移动事件,但是还在在小图片盒子里移动
  • 遮挡层盒子大小一半

在这里插入图片描述

window.addEventListener('load',function(){//获取到对象var preview_img = document.querySelector('.preview_img'); //图片var mask = document.querySelector('.mask'); //遮挡层var big = document.querySelector('.big'); //大图片//1.当我们鼠标经过图片的时候,就显示和隐藏遮挡层preview_img.addEventListener('mouseover',function(){mask.style.display = 'block';   //遮挡层显示big.style.display = 'block';    //大图片显示});//2. 鼠标移动的时候,让黄色的黑子跟着鼠标走preview_img.addEventListener('mousemove',function(e){//(1)先计算出鼠标在盒子内的坐标var x = e.pageX - this.offsetLeft;var y = e.pageY - this.offsetTop;console.log(x,y);//(2)减去盒子高度 300的一半(也就是得到150),就我们的这个mask最终的left和top的值var maskX = x - mask.offsetWidth/2;var maskY = y - mask.offsetHeight/2;//(3)我们mask移动//(4)如果x坐标小于了0,就让他停在0的位置var maskMax = preview_img.offsetWidth - mask.offsetWidth;if(maskX <= 0){maskX = 0;} else if(maskX >= maskMax){maskX = maskMax;}if(maskY <= 0){maskY = 0;} else if(maskY >= maskMax){maskY = maskMax;}mask.style.left = maskX + 'px';mask.style.top = maskY + 'px';//3.大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离//大图var bigImg = document.querySelector('.bigImg');//大图最大移动距离var bigMax = bigImg.offsetWidth - big.offsetWidth;//大图片移动距离xyvar bigX = maskX * bigMax / maskMax;var bigY = maskY * bigMax / maskMax;bigImg.style.left = -bigX + 'px';bigImg.style.top = -bigY + 'px';})
});

二、元素可视区client系列

1.client概述

client翻译过来客户端,我们使用client系列相关的属性来获取元素可视区的相关信息。通过client系列的先骨干属性可以动态的得到该元素的边框大小、元素大小等

Client系列的属性说明
element.clientTop返回呀u盛怒的上边框的大小
element.clientLeft返回元素左边框的大小
element.clientWidth返回自身包括padding、内容的宽度、不含边框,返回的数值不带单位
element.clientHeight返回自身包括padding、内容的宽度、不含边框,返回的数值不带单位

2.例子

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;background-color: pink;border: 10px solid red;padding: 10px;}</style>
</head>
<body><div></div><script>//client 宽度 和我们offsetWidth最大的区别就是不包含边框var div = document.querySelector('div');console.log(div.clientWidth); //220  (不包含border)</script>
</body>
</html>

3.淘宝flexible.js源码分析

(function flexible(window, document) {//获取html的根元素var docEl = document.documentElement//dpr 物理像素比var dpr = window.devicePixelRatio || 1// adjust body font size  设置我们body的字体大小function setBodyFontSize() {// 如果页面中由body这个元素 ,就设置body的字体大小if (document.body) {document.body.style.fontSize = (12 * dpr) + 'px'} else {//如果页面中的body没有这个元素,则等着,我们页面主要的dom元素加载完毕后再去设置body的字体大小document.addEventListener('DOMContentLoaded', setBodyFontSize)}}setBodyFontSize();// set 1rem = viewWidth / 10    设置我们html元素的字体大小function setRemUnit() {var rem = docEl.clientWidth / 10docEl.style.fontSize = rem + 'px'}setRemUnit()// reset rem unit on page resize  当我们页面的尺寸发生变化,要重新设置rem的大小window.addEventListener('resize', setRemUnit)// pageShow 是我们重新加载页面触发的事件window.addEventListener('pageshow', function(e) {//e.persisted 返回的是true表示这个页面是从缓存中读取过来的页面,也就需要重新计算以下rem的大小if (e.persisted) {setRemUnit()}})// detect 0.5px supports   有些移动端的浏览器不支持0.5像素的写法if (dpr >= 2) {var fakeBody = document.createElement('body')var testElement = document.createElement('div')testElement.style.border = '.5px solid transparent'fakeBody.appendChild(testElement)docEl.appendChild(fakeBody)if (testElement.offsetHeight === 1) {docEl.classList.add('hairlines')}docEl.removeChild(fakeBody)}
}(window, document))

立即执行函数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>07.立即执行函数</title>
</head>
<body><script>//1.立即执行函数function fn(){console.log();}fn();//2.传递参数//语法: (function(){}) ()  或者  (function 函数名(){}())(function(a,b){console.log(a + b);var num = 10; //局部变量})(1,2);  //一共有两个括号()(),第一个括号里是函数,第二个括号是调用函数(function(){console.log('abc');})()//或者(function sum(a,b) {console.log(a + b);//var num = 10; //局部变量}(2,3));console.log(num);</script>
</body>
</html>

三、元素滚动scroll 系列

1.概述

scroll 翻译过来就是滚动,我们使用scroll系列相关属性可以动态的得到该元素的大小、滚动的距离等

scroll系列属性说明
element.scrollTop返回被卷去的上侧距离,返回数值不带单位
element.scrollLeft返回被卷去的左侧距离,返回数值不带单位
element.scrollWidth返回自身实际的宽度,不含边框,返回值不带单位
element.scrollHeight返回自身实际的高,不含边框,返回值不带单位
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;background-color: pink;border: 10px solid red;padding: 10px;overflow: auto;}</style>
</head>
<body><div>我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容</div><script>//scroll系列var div = document.querySelector('div');console.log(div.scrollHeight); //会计算滚动的内容console.log(div.clientHeight); //大盒子的高度div.addEventListener('scroll',function(){console.log(div.scrollTop); //滚动条距离上面的距离});</script>
</body>
</html>

2.仿京东回到顶部

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.slider-bar {position: absolute;left: 50%;top: 300px;margin-left: 600px;width: 45px;height: 130px;background-color: pink;}.main{width: 1200px;margin: 10px auto;height: 1000px;background-color: yellowgreen;}.header{height: 150px;background-color: purple;}.banner{height: 250px;background-color: skyblue;}span{position: absolute;display: none;bottom: 0;cursor: pointer;}</style>
</head>
<body><div class="slider-bar"><span class="goBack">返回顶部</span></div><div class="header">头部区域</div><div class="banner">banner区域</div><div class="main">主体部分</div><script>//1.获取元素var sliderbar = document.querySelector('.slider-bar');var banner = document.querySelector('.banner');//banner.offsetTop就是被卷去头部的大小,一定要写到滚动外面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.页面滚动事件scrolldocument.addEventListener('scroll',function(){// console.log('bannerTop--->' + bannerTop);// console.log('sliderbarTop--->' + sliderbarTop);//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>
</body>
</html>

四、三大系列总结

三大系列大小对比作用
element.offsetWidth返回包括padding、边框、内容去的宽度,返回值不带单位
element.clientWidth返回包括padding、内容区域宽度、不含边框,返回值不带单位
element.scrollWidth返回自身的实际宽度,不含边框,返回数值不带单位

主要用法:

  • offset系列经常用于获得元素的位置,offsetLeft、offsetTop
  • client经常用于获取元素的大小、clientWith、clientHight
  • scroll经常用于获取滚动距离:scrollTop、scrollLeft
  • 注意:页面滚动距离是通过 window.pagetXOffset/pagetYOffset 获取

五、mouseenter和mouseover的区别

  • 当鼠标移动到元素上的时候会触发mouseenter事件
  • 类似mouseover、他们两者之间有差别
    • mouseover鼠标经过盒子的时候触发、再次经过还是会触发。mouseenter只会经过自身盒子触发,之所以这样,是因为mouseenter不会冒泡
    • 跟mouseenter搭配鼠标离开的是mouseleave同样也不会冒泡
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>mouseenter和mouseover的区别</title><style>.father{width: 300px;height: 300px;background-color: pink;margin: 100px auto;}.son {width: 200px;height: 200px;background-color: purple;}</style>
</head>
<body><div class="father"><div class="son"></div></div><script>var father = document.querySelector('.father');var son = document.querySelector('.son');father.addEventListener('mouseenter',function(){console.log(111111);});son.addEventListener('mouseenter',function(){console.log(22222);});</script>
</body>
</html>

六、动画函数封装

1.动画原理

核心原理:通过定时器setInterval不断移动盒子的位置

2.实现步骤

  • 获取盒子当前的位置
  • 让盒子再档期那位置上加1个移动距离
  • 利用定时器不断重复这个操作
  • 加上一个结束定时器条件
  • 注意此元素要添加定位,才能使用element.style.left
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{position: absolute;left: 0;width: 100px;height: 100px;background-color: pink;}</style>
</head>
<body><div></div><script>// - 获取盒子当前的位置// - 让盒子再档期那位置上加1个移动距离// - 利用定时器不断重复这个操作// - 加上一个结束定时器条件// - 注意此元素要添加定位,才能使用element.style.leftvar div = document.querySelector('div');var timer = setInterval(function(){//添加动画结束的条件if(div.offsetLeft >= 400){//停止动画 clearInterval(timer);}div.style.left = div.offsetLeft + 1 + 'px';},20);</script>
</body>
</html>

3.简单动画封装

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{position: absolute;left: 0;width: 100px;height: 100px;background-color: pink;}span{display: block;position: absolute;left: 0;top: 200px;width: 150px;height: 150px;background-color: purple;}</style>
</head>
<body><div>房祖名</div><span>蔡徐坤</span><script>//简单动画函数封装obj目标对象target目标位置function animate(obj,target){var timer = setInterval(function(){if(obj.offsetLeft >= target){//停止动画clearInterval(timer);}obj.style.left = obj.offsetLeft + 1 + 'px';},20);}//获取对象var div = document.querySelector('div');var span = document.querySelector('span');//调用函数animate(div,300);animate(span,200)</script>
</body>
</html>

4.给不同的对象添加不同的定时器

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>14.不同的对象使用不同的定时器</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>点击蔡徐坤开始打篮球</button><div></div><span>蔡徐坤</span><script>//简单动画函数封装obj目标对象target目标位置function animate(obj,target){//当我们不断的点击按钮,这个元素的速度会越来越快吗?因为开了太多的定时器//解决方案:让我们的元素只有一个定时器执行,每次点击就把前面的定时器清除掉clearInterval(obj.timer);obj.timer = setInterval(function(){if(obj.offsetLeft >= target){clearInterval(obj.timer);}obj.style.left = obj.offsetLeft + 1 + 'px';},20);}//获取对象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>
</body>
</html>

http://www.mrgr.cn/news/56114.html

相关文章:

  • Python语法探索:解锁编程艺术的大门
  • Java爬虫:API数据界的“宝藏猎人”
  • SqlDbx连接oracle(可用)
  • 什么是 SQL 注入攻击?如何防止 SQL 注入?
  • uoload-labs靶场Pass-09
  • MySQL备份和还原,用mysqldump、mysql和source命令来完成
  • 【vue之道】
  • python中如何获取对象信息
  • 详解Java之Spring MVC篇一
  • SSM网上书店管理系统—计算机毕业设计源码41539
  • 如何将 Docker 镜像的 tar 文件迁移到另一台服务器并运行容器
  • 焊接原因引起的RJ45网口连接器LED灯不亮原因分析及处理措施
  • Redis Search系列 - 第四讲 支持中文
  • pip安装basicsr和tb-nightly报错
  • deepin V23 部署Ollama
  • BurpSuite渗透工具的简单使用
  • 如何利用动态IP对市场进行产品调研分析?
  • 华为不同职级,薪资待遇一览表
  • 移动用户心理:如何让他们安装和使用你的应用
  • C# lambda表达式语法简介
  • Python Numpy 实现神经网络自动训练:反向传播与激活函数的应用详解
  • 【Linux】进程优先级进程切换
  • centos7 使用yum卸载redis3.2版本并安装redis5版本
  • 后端:唯一ID有哪些生成方式
  • 有趣的css - 拉链式展开按钮
  • 天锐绿盾 vs Ping32:企业级加密软件大比拼