三、DOM
- 文档对象模型
- 操作html标签的能力
- 操作
- 获取一个元素
- 移除一个元素
- 创建一个元素
- 向页面添加一个元素
- 给元素绑定一些元素
- 获取元素的属性
- 给元素添加一些css样式
- 核心是
document对象 document对象是浏览器内置的一个对象,里面存储专门用来操作元素的各种方法
1.获取一个元素
1.1 html元素
document.documentElement
1.2 head
document.head
1.3 body
document.body
1.4 获取id元素
document.getElementsById(id名称)- 无兼容性问题
- 只能是一个对象,就算有两个或
1.5 获取class元素
document.getElementsByClassName(class名字)- 伪数组:长的像一个数组,实际上不是真正的数组,没有.map属性
- 真正的数组有.map等属性
<body>
<ul>
<li class="li_name">111</li>
<li class="li_name">111</li>
<li class="li_name">111</li>
<li class="li_name">111</li>
<li class="li_name">111</li>
</ul>
<script>
var class_name = document.getElementsByClassName("li_name")
console.log(class_name[0].map) //undefined
class_name[0].innerHTML = "hello"
var newitems = Array.from(class_name) //转换为字符串
console.log(newitems.map) //ƒ map() { [native code] }
</script>
</body>
1.6 获取标签名
document.getElementsByTagName(标签名称li)- 和获取class用法类似
1.7 获取name元素
document.getElementsByName(name名称)- 只适用于
input标签 document.getElementsByName(name名称).value = 'HELLO'
1.8 querySelector
- 对低版本浏览器不友好
- 与css一样的操作
- 多个同名则返回第一个遇到的对象
<body>
<ul>
<li class="li_name">1</li>
<li class="li_name">2</li>
<li class="li_name">3</li>
<li class="li_name">4</li>
<li class="li_name">5</li>
</ul>
<script>
var item = document.querySelector("li")
console.log(item) //<li class='li_name'>1</li>
</script>
</body>
1.9 querySelectorAll
- 相比上面的区别
- 遇到多个同名的,返回所有
<body>
<ul>
<li class="li_name">1</li>
<li class="li_name">2</li>
<li class="li_name">3</li>
<li class="li_name">4</li>
<li class="li_name">5</li>
</ul>
<script>
var item = document.querySelectorAll("ul li.li_name")
console.log(item) // NodeList(5) [li.li_name, li.li_name, li.li_name, li.li_name, li.li_name]
</script>
</body>
2.操作元素
2.1属性
- 元素自带(原生)属性
- 自定义属性
<div class="box" dkwwwwww="danorz">hello</div>
//class 元素属性 dkwwwwww 自定义属性
- 操作原生属性
<body>
<div id="box" dkwwwwww="danorz">hello</div>
<input type="text" value="hello" id="username" >
<script>
box.innerHTML = "222"
username.value = "3333"
username.type = "password"
</script>
</body>
- 操作自定义属性
- 设置属性
setAttribute("key","value") - 获取属性
getAttribute("key") - 移走属性
removeAttribute("key") - 命名规则:
data-XXX - 设置属性
.dataset.新属性名 = 属性值 - 删除属性
delete .dataset.属性名 - 获取属性
.dataset
- 设置属性
<body>
<div id="box">hello</div>
<div id="box2" data-aaa="a">yes</div>
<script>
box.setAttribute("dan","me")
console.log(box.getAttribute("dan"))
box.removeAttribute("dan")
box2.dataset.bbb="b"
delete box2.dataset.aaa
console.log(box2.dataset)
</script>
</body>
1.2.1 显示密码
<body>
<input type="password" id="password">
<button id="change">显示</button>
<script>
var password = document.getElementById('password')
var change = document.querySelector('#change')
console.log(password)
change.onclick = function(){
if (password.type === 'password'){
password.type = 'text'
} else {
password.type = 'password'
}
}
</script>
</body>
1.2.2 购物车全选功能
<body>
<input type="checkbox" id="all">全选
<hr>
<ul class="shop">
<li>
<input type="checkbox">goods1
</li>
<li>
<input type="checkbox">goods2
</li>
<li>
<input type="checkbox">goods3
</li>
<li>
<input type="checkbox">goods4
</li>
<li>
<input type="checkbox">goods5
</li>
</ul>
<script>
var all = document.getElementById('all')
var items = document.querySelectorAll(".shop input")
all.onclick = function(){
console.log(items.length)
if( all.checked == true ){
for(var i = 0; i < items.length; i++){
items[i].checked = true
}
} else {
for(var i = 0; i < items.length; i++){
items[i].checked = false
}
}
}
for (var i = 0; i<items.length ; i++){
items[i].onclick = handler
}
function handler(){
var count = 0
for(var i =0; i<items.length; i++){
if(items[i].checked) count++
}
if(count === items.length){
all.checked = true
} else {
all.checked = false
}
}
</script>
</body>
2.2 操作元素文本内容
- innerHTML
- 拿到文本和标签
- 设置:能设置标签和文本
- innerText
- 只拿文本信息
- 不解析HTML
- 设置:文本
- value
- 表单input、下拉选项select
2.2.1 渲染页面
<body>
<ul></ul>
<script>
var filmList = [ { url:'https://static.maizuo.com/pc/v5/usr/movie/149ddb9a7f64e06ed474d963cfc6c405.jpg?x-oss-process=image/quality,Q_70', title:'消失的她', grade:7.1 }, { url:'https://static.maizuo.com/pc/v5/usr/movie/19dbbdc52057e722a4c6d76a788fc417.jpg?x-oss-process=image/quality,Q_70', title:'我爱你!', grade:7.4 }, { url:'https://static.maizuo.com/pc/v5/usr/movie/b6be063ea8bb7d4ecd09299b800fe510.jpg?x-oss-process=image/quality,Q_70', title:'八角笼中', grade:7.3 } ]
var filmItems = filmList.map(function(item){
return `<li>
<img src='${item.url}'>
<h3>${item.title}</h3>
<p>观众评分 ${item.grade}</p>
</li>`
})
console.log(filmItems.join(""))
var ul = document.querySelector('ul')
ul.innerHTML = filmItems.join('')
</script>
</body>
2.3 操作元素样式
- 行内样式
- 获取
.style.样式- background-color两种写法
backgroundColorstyle['background-color']
- background-color两种写法
- 设置样式
.style.样式 = "XX"
- 获取
<body>
<div id="box" style="width: 100px;color: blueviolet;background-color: blue;">111</div>
<script>
console.log(box.style.width)
console.log(box.style.backgroundColor)
console.log(box.style['background-color'])
box.style.height = '1000px'
console.log(box.style.height)
</script>
</body>
- 内部样式、外部样式、行内样式
- 只能读取,不能写
getComputedStyle(节点名称).css样式- background-color两种写法
.backgroundColorgetComputedStyle(节点名称)['background-color']
- background-color两种写法
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01.html</title>
<style>
#box {
height: 100px;
background-color: blue;
}
</style>
</head>
<body>
<div id="box">111</div>
<script>
var a = getComputedStyle(box).height
var b = getComputedStyle(box)['background-color']
var c = getComputedStyle(box).backgroundColor
console.log(a,b,c)//100px rgb(0, 0, 255) rgb(0, 0, 255)
</script>
</body>
- ie浏览器 低版本
.currentStyle.css样式
2.4 操作元素类名
- className
- 查看class类名
.className - 修改类名
.className = " 新类名 "/.className += ' 新类名' - 有重复的不会去重
- 查看class类名
<body>
<div id="box" class="item item1 item2 ">111</div>
<script>
console.log(box.className)// item item1 item2
box.className = 'item item2'
console.log(box.className)//item item2
box.className += " item3"
console.log(box.className)// item item2 item3
box.className = "item item2 item3 item4"
console.log(box.className) // item item2 item3 item4
</script>
</body>
- classList
- 有重复的能去重
- 添加
.classList.add('item2') - 删除
.classList.remove('item2') - 切换
.classList.toggle("item2")
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01.html</title>
<style>
.it2 {
background-color: blue;
}
</style>
</head>
<body>
<div id="box" class="item">111</div>
<button id="btn" class="it">222</button>
<script>
console.log(box.classList)
var a = box.classList.add('item2')
console.log(box.classList)
var b = box.classList.remove('item')
console.log(box.classList)
btn.onclick = function(){
box.classList.toggle("it2")
}
</script>
</body>
2.4.1 简易选项卡
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01.html</title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
display: flex;
list-style: none;
}
li {
height: 50px;
line-height: 50px;
text-align: center;
flex: 1;
}
.active {
color: red;
border-bottom: 1px solid red;
}
</style>
</head>
<body>
<ul>
<li id="item" class="active">正在热映</li>
<li id="item2" >即将上映</li>
</ul>
<script>
var li1 = document.querySelector("#item")
var li2 = document.querySelector("#item2")
li1.onclick = function(){
li2.classList.remove('active')
li1.classList.add("active")
}
li2.onclick = function(){
li1.classList.remove('active')
li2.classList.add("active")
}
</script>
</body>
2.4.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>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.header {
display: flex;
width: 500px;
}
.header li {
flex: 1;
height: 50px;
line-height: 50px;
text-align: center;
border: 1px solid black;
}
.box {
position: relative;
}
.box li {
position: absolute;
left: 0;
top: 0;
width: 500px;
height: 200px;
background-color: yellow;
display: none;
}
.header .active {
background-color: red;
}
.box .active {
display: block;
}
</style>
</head>
<body>
<ul class="header">
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul class="box">
<li class="active">111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
<script>
var oHeaderItems = document.querySelectorAll('.header li')
var oBoxItems = document.querySelectorAll('.box li')
for (var i=0 ; i<oHeaderItems.length; i++) {
oHeaderItems[i].dataset.index = i
oBoxItems[i].dataset.index = i
oHeaderItems[i].onclick = function(){
var index = this.dataset.index
for(var m=0; m<oHeaderItems.length; m++) {
oHeaderItems[m].classList.remove('active')
oBoxItems[m].classList.remove('active')
}
oHeaderItems[index].classList.add('active')
oBoxItems[index].classList.add('active')
}
}
console.log(i)
</script>
</body>
</html>
3.DOM节点
- 分类:元素节点/文本节点/属性节点
3.1 元素节点
- div p li ....
- document 是根节点
- 元素最大的节点
- 所有节点都不是,是承载使用的节点
- html 根元素节点
- 一个页面最大的元素节点
3.2 文本节点
<div>XXXX</div>中的XXX就是文本节点- 换行符也算一个节点\n
3.3 属性节点
- id class style...
<div class='job'>XXX</div>
- 获取属性节点
getAttribute('index') - 所有属性节点
attributes
<body>
<div id="box" index="1">
rose
<p id="box_next">i am a p tag</p>
<!-- woshiyigezhushi -->
</div>
<script>
console.log(box.getAttribute('index')) //1
console.log(box.attributes)//NamedNodeMap {0: id, 1: index, id: id, index: index, length: 2}
console.log(box.attributes[1]) //index='1'
</script>
</body>
3.4 注释节点
<!- 我是一段注释-->
4.获取节点
- 所有节点
childNodes - 所有元素
children - 第一个孩子节点
firstChild - 第一个元素节点
firstElementChild - 最后一个孩子节点
lastChild - 最后有一个元素节点
lastElementChild - 上一个兄弟节点
previousSibling - 上一个元素节点
previousElementSibling - 下一个兄弟节点
nextSibling - 下一个兄弟元素节点
nextElementSibling - 父节点
parentNode - 父元素节点
parentElement- 拿不到就是null
<body>
<div id="box">
rose
<p>i am a p tag</p>
<!-- woshiyigezhushi -->
</div>
<div id="box1">rose<p>i am a p tag</p><!-- woshiyigezhushi --></div>
<script>
console.log(box.childNodes)//5个节点 查看data
console.log(box1.childNodes)//3个节点
console.log(box.children)
console.log(box.firstChild)
console.log(box.firstElementChild)
console.log(box1.previousSibling) //#text
console.log(box1.previousElementSibling) //<div id='box'>
console.log(box.nextSibling)
console.log(box.nextElementSibling)
console.log(box.parentNode) //body
console.log(box.parentElement)//body
</script>
</body>
5. 操作DOM节点
5.1 创建节点
- 创建孩子节点最后一个
apprendChild()
<body>
<div id="box">
<div id="child">i am first querncard !</div>
</div>
<script>
var odiv = document.createElement('div')
odiv.className = 'aaa'
odiv.id = 'a'
odiv.style.background = 'yellow'
odiv.innerHTML = 'is you ?'
console.log(odiv)
box.appendChild(odiv)
</script>
</body>
- 插入当前节点之前
.insertBefore('要插入的节点', '谁的前面插入')
box.insertBefore(odiv,child)
5.2 删除节点
- 删除节点
removeChild(节点对象)
box.removeChild(child)
- 删除当前节点
remove()
box.remove()
5.3 替换节点
- 替换节点
replaceChild(替换节点, 被替换节点)
<body>
<div id="box">
<div id="child">i am first querncard !</div>
</div>
<script>
var odiv2 = document.createElement('div')
odiv2.innerHTML = '222'
box.replaceChild(odiv2,child)
</script>
</body>
5.4 克隆节点
clonNode()- 默认: 克隆节点(false) 不克隆后代
- true 克隆后代
<body>
<div id="box">
<div id="child">i am first querncard !</div>
</div>
<script>
var oCloneBox = box.cloneNode(true)
console.log(oCloneBox)
document.body.appendChild(oCloneBox)
oCloneBox.id = 'box2'
</script>
</body>
5.5 案例: 动态删除
- 每个li配一个button
- 点击删除,删除当前li
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
ul {
list-style: none;
}
</style>
</head>
<body>
<ul id="box">
</ul>
<script>
var arr = ['111','222','333']
for(var i = 0; i < arr.length; i++) {
var oli = document.createElement('li')
var obutton = document.createElement('button')
// 添加内容
oli.innerHTML = arr[i]
obutton.innerHTML = 'detele'
oli.id = 'li' + i
obutton.onclick = deloli
box.appendChild(oli)
oli.appendChild(obutton)
}
function deloli() {
this.parentNode.remove()
}
</script>
</body>
6. 节点属性
| nodeType | nodeName | nodeValue | |
|---|---|---|---|
| 元素节点 | 1 | 大写标签名 null | |
| 属性节点 | 2 | 属性名 | 属性值 |
| 文本节点 | 3 | #text | 文本内容 |
<body>
<div class="box">hello world<!--chenruoshuang --></div>
<script>
var odiv = document.querySelector('.box')
console.log(odiv.childNodes)
for (var i = 0; i < odiv.childNodes.length; i++) {
var a = odiv.childNodes[i].nodeType
console.log(a)
}
</script>
</body>
7. 获取元素尺寸
-
offsetWidth: 内容+padding+border -
offsetHeight: 内容+padding+border- 类型: 数字
- border-sizing: width的长度
- display:none 拿不到
-
clientWidth: 内容+padding -
clientHeight: 内容+padding- 类型: 数字
- border-sizing: width-border的长度
- display:none 拿不到
<style>
.box {
width: 100px;
height: 100px;
padding: 10px;
border: 5px solid red;
background-color: yellow;
}
</style>
<body>
<div class="box"></div>
<script>
var odiv = document.querySelector('.box')
console.log(odiv.offsetWidth,odiv.offsetHeight)//130 130
</script>
</body>
<style>
.box {
width: 100px;
height: 100px;
padding: 10px;
border: 5px solid red;
background-color: yellow;
box-sizing: border-box;
}
</style>
<body>
<div class="box"></div>
<script>
var odiv = document.querySelector('.box')
console.log(odiv.clientHeight,odiv.clientWidth)
</script>
</body>
8. 定位距离
offsetLeftoffsetTopoffsetRightoffsetBottom- 参考点: 定位父级
- 若父级元素都没有定位
position:relative,偏移量想到对于body节点
- 若父级元素都没有定位
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 500px;
height: 500px;
background-color: yellow;
overflow: hidden;
}
#myparent {
width: 300px;
height: 300px;
background-color: blue;
overflow: hidden;
}
#child {
width: 100px;
height: 100px;
background-color: red;
}
div {
margin: 50px;
}
</style>
<body>
<div id="box">
<div id="myparent">
<div id="child">
</div>
</div>
</div>
<script>
console.log(box.offsetTop,box.offsetLeft) // 50 50
console.log(myparent.offsetTop,myparent.offsetLeft) // 100 100
console.log(child.offsetTop,child.offsetLeft) // 150 150
</script>
</body>
9. 边框的宽度
clientLeftclientRightclientTopclientBottom
<style>
* {
margin: 0;
padding: 0;
}
ul {
width: 200px;
height: 200px;
padding: 20px;
border: 10px solid black;
background-color: red;
margin: 50px;
}
</style>
<body>
<ul id="list"></ul>
<script>
console.log(list.clientLeft,list.clientTop) // 10 10
</script>
</body>
<style>
* {
margin: 0;
padding: 0;
}
ul {
width: 200px;
height: 200px;
padding: 20px;
border: 10px solid black;
background-color: red;
margin: 50px;
border-left-width: 50px;
border-top-width: 50px;
}
</style>
<body>
<ul id="list"></ul>
<script>
console.log(list.clientLeft,list.clientTop) // 50 50
</script>
</body>
10 案例 滚动加载数据
<style>
* {
margin: 0;
padding: 0;
}
html,body {
height: 100%;
}
ul li {
overflow: left;
height: 150px;
}
ul li img {
float: left;
width: 80px;
}
</style>
<body>
<h1>标题</h1>
<ul id="list">
</ul>
<script>
var arr1 = [
{
name:'11',
url: './img001.JPG'
},
{
name:'22',
url: './img001.JPG'
},
{
name:'33',
url: './img001.JPG'
},
{
name:'44',
url: './img001.JPG'
},
{
name:'55',
url: './img001.JPG'
}
]
var arr2 = [
{
name:'66',
url: './img001.JPG'
},
{
name:'77',
url: './img001.JPG'
},
{
name:'88',
url: './img001.JPG'
},
{
name:'99',
url: './img001.JPG'
},
{
name:'00',
url: './img001.JPG'
}
]
renderHTML(arr1)
function renderHTML(arr) {
// list.innerHTML += arr.map((item) => {
// return `<li>
// <img src="${item.url}" alt="">
// <h3>${item.name}</h3>
// </li>`
// }).join('')
// += 会再次加载 界面会闪一下
//用append则不会是在原有的基础上加上节点
arr.forEach((item) => {
var oli = document.createElement('li')
oli.innerHTML = `<img src="${item.url}" alt="">
<h3>${item.name}</h3>`
list.appendChild(oli)
})
}
var isLoading = false
window.onscroll = () => {
var listHeight = list.offsetHeight //整个list的高度 750 = 5 * 150
var listTop = list.offsetTop // list距离body的top值,偏移量
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop// 屏幕滚动的距离
var windowHeight = document.documentElement.clientHeight // 屏幕可以展示的宽度
if (isLoading) return
// if (Math.round(windowHeight + scrollTop) >= (listHeight+listTop - 100)) {
// console.log('到底了')
// isLoading = true
// }
if ( (listHeight+listTop -Math.round(windowHeight + scrollTop) )<50) {
console.log('到底了')
isLoading = true
setTimeout(() => {
renderHTML(arr2)
isLoading = false //下一次到底数据继续触发
},1000) //在真实案例中会向后端请求
}
}
</script>
</body>
11. 事件
11.1 绑定事件
.事件- 缺点: 多个时,以最后一个为主
.addEventListener('事件',function)
<body>
<div id="box">点击我</div>
<script>
box.onclick = () => {
console.log('11111')
}
box.onclick = () => {
console.log('2222')
}//下面的click事件会覆盖掉上面的点击事件
box.addEventListener('click',()=>{
console.log('3333')
})// 可以绑定多个点击事件
box.addEventListener('click',()=>{
console.log('444')
})//显示3个点击事件 2222 3333 444
</script>
</body>
11.2 解绑事件
this.onclick = null
<body>
<button id="btn">点击我</button>
<script>
// btn.onclick = function() {
// console.log('11111')
// this.onclick = null
// }
btn.onclick = (e) => {
console.log('11111')
// console.log(e.target)
e.target.onclick = null
}
</script>
</body>
removeEventListener('事件',函数)
- 有兼容性问题IE浏览器
<body>
<button id="btn">点击我</button>
<script>
function handle (){
console.log('111')
this.removeEventListener('click',handle)
}
btn.addEventListener('click',handle)
</script>
</body>
- 兼容ie
<body>
<button id="btn">点击我</button>
<script>
function handler (){
console.log('111')
btn.detachEvent('onclick',handler)
}
btn.attachEvent('onclick',handler)
</script>
</body>
11.3 事件类型
- 鼠标事件
- onclick
- ondblclick 双击事件
- oncontextmenu 右键单击
- onmousedown 鼠标按下
- onmousemove 鼠标移动
- onmouseup 鼠标抬起
- onmouseover onmouseout 移入移出
- onmouseenter onmouseleave 移入移出
- 区别: 前者孩子节点的移入移出也会显示; 后者不显示孩子节点的移入移出
<body>
<button id="btn">点击我</button>
<script>
//鼠标事件
// btn.ondblclick = () => {
// console.log('ondblclick')
// }
// btn.oncontextmenu = () => {
// console.log('oncontextmenu')
// }
// btn.onmousedown = () => {
// console.log('onmousedown')
// }
// btn.onmousemove = () => {
// console.log('onmousemove')
// }
// btn.onmouseup = () => {
// console.log('onmouseup')
// }
</script>
</body>
<style>
#box {
width: 200px;
height: 200px;
background-color: yellow;
}
#child {
width: 100px;
height: 100px;
background-color: purple;
}
</style>
<body>
<div id="box">
<div id="child">
</div>
</div>
<script>
//鼠标事件
// box.onmouseover = () => {
// console.log('移入')
// }
// box.onmouseout = () => {
// console.log('移出')
// }
// box.onmouseenter = () => {
// console.log('移入')
// }
// box.onmouseleave = () => {
// console.log('移出')
// }
</script>
</body>
- 键盘事件
- onkeydown 按下键盘
- onkeyup 松开键盘
<body>
<input type="text" id="username">
<script>
//键盘事件
username.onkeydown = () => {
console.log("按下键盘",'判断是不是回车键')
}
username.onkeyup = () => {
console.log("放开键盘",'判断是不是回车键')
}
</script>
</body>
-
浏览器事件
- onload 页面全部资源加载完毕
- onscroll 浏览器滚动的时候触发
-
表单事件
- onfocus 获取焦点
- onblur 失去焦点
- onchange 对比获取焦点和失去焦点里面的内容不一样才会触发
- oninput 内容不一样就触发
- onreset 重置
- onsubmit 提交
<input type="text" id="username">
<script>
//表单事件
username.onfocus = () => {
console.log('获取焦点')
}
username.onblur = () => {
console.log('失去焦点')
}
// username.onchange = () => {
// console.log('onchange')
// }
username.oninput = () => {
console.log('input')
}
</script>
<body>
<form action="" id="myform">
<input type="text" id="username">
<input type="reset">
<input type="submit" value="提交">
</form>
<script>
//表单事件
myform.onsubmit = () => {
console.log('submit')
return false
}
myform.onreset = () => {
console.log('reset')
}
</script>
</body>
- 移动事件
- ontouchstart 开始触摸
- ontouchomve 在移动
- ontouchend 结束触摸
- 左划右划等都是基于上述三个事件
- ontouchcancel 在浏览网页时,突然有电话
<style>
#box {
width: 200px;
height: 200px;
background-color: yellow;
}
</style>
<body>
<div id="box"></div>
<script>
//触摸事件
box.ontouchstart = () => {
console.log('ontouchstart')
}
box.ontouchmove = () => {
console.log('ontouchmove')
}
box.ontouchend = () => {
console.log('ontouchend')
}
box.ontouchcancel = () => {
console.log('touchcancle')
}
</script>
</body>
11.4 事件对象
- clientX clientY 距离浏览器可视窗口左上角坐标值的距离,会随着滚动条变化而变化
- pageX pageY 距离浏览器可视窗口的左上角坐标值
- offsetX offsetY 相对于盒子的左上角坐标值,距离实际触发的元素左上角的距离
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 2000px;
height: 2000px;
}
div {
width: 200px;
height: 200px;
background-color: blue;
margin: 100px;
}
p {
width: 100px;
height: 100px;
background-color: red;
margin: 100px;
}
</style>
<body>
<div id="box">
<p>
</p>
</div>
<script>
box.onclick = (evt) => {
// console.log(evt)
console.log(evt.clientX,evt.clientY,'clientX')
console.log(evt.pageX,evt.pageY,'pageX')
console.log(evt.offsetX,evt.offsetY,'offsetX')
}
</script>
</body>
11.5 案例:鼠标跟随
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 200px;
height: 50px;
background-color: yellow;
position: relative;
margin: 100px;
}
#box p {
width: 300px;
height: 200px;
background-color: red;
position: absolute;
left: 100;
top: 100;
display: none;
/* pointer-events: none; */
/* 方法二: 防止穿透; 缺点:若后面有div标签,会把p标签盖住,层级低; 解决: z-index:number*/
}
</style>
<body>
<div id="box">
chenrruoshuang的头像
<p>
chenruoshaung的介绍
</p>
</div>
<script>
box.onmouseover = function () {
this.firstElementChild.style.display = 'block'
}
box.onmouseout = function (evt) {
this.firstElementChild.style.display = 'none'
}
box.onmousemove =function (evt) {
// this.firstElementChild.style.left = evt.offsetX + 20 + 'px'
// this.firstElementChild.style.top = evt.offsetY + 20 +'px'
//方法一: + 20 防止触碰到p标签
this.firstElementChild.style.left = evt.offsetX + 'px'
this.firstElementChild.style.top = evt.offsetY +'px'
}
</script>
</body>
11.6 鼠标拖拽
- 方法一
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 100px;
height: 100px;
background-color: skyblue;
/* position: relative; */
position: absolute;
}
</style>
<body>
<div id="box">
</div>
<script>
box.onmousedown = function() {
console.log('down')
console.log(document)
document.onmousemove = function(evt) {
console.log('move')
var x = evt.clientX - box.offsetWidth/2
var y = evt.clientY - box.offsetHeight/2
if ( y <= 0 ) y = 0
if ( x <= 0 ) x = 0
if (y>= document.documentElement.clientHeight - box.offsetHeight) y = document.documentElement.clientHeight - box.offsetHeight
if (x>= document.documentElement.clientWidth - box.offsetWidth) x = document.documentElement.clientWidth - box.offsetWidth
box.style.left = x +'px'
box.style.top = y + 'px'
}
}
box.onmouseup = function() {
console.log('up')
document.onmousemove = null
}
</script>
</body>
- 方法二
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 100px;
height: 100px;
background-color: skyblue;
/* position: relative; */
position: absolute;
}
</style>
<body>
<div id="box">
</div>
<script>
var isDown = false
box.onmousedown = function() {
isDown = true
console.log('down')
console.log(document)
}
box.onmouseup = function() {
isDown = false
console.log('up')
// document.onmousemove = null
}
document.onmousemove = function(evt) {
if(!isDown) return
console.log('move')
var x = evt.clientX - box.offsetWidth/2
var y = evt.clientY - box.offsetHeight/2
if ( y <= 0 ) y = 0
if ( x <= 0 ) x = 0
if (y>= document.documentElement.clientHeight - box.offsetHeight) y = document.documentElement.clientHeight - box.offsetHeight
if (x>= document.documentElement.clientWidth - box.offsetWidth) x = document.documentElement.clientWidth - box.offsetWidth
box.style.left = x +'px'
box.style.top = y + 'px'
}
</script>
</body>