1.页面返回顶部
要求: 点击按钮之后可以由快到慢地回到顶部,处于顶部位置时按钮消 失,按钮位于页面的右下方
解:1.绑定滚动事件
(1)获取页面高度;(2)设置if语句显示/隐藏按钮
2.绑定点击事件
(1)设置滚动位置;(2)设置滚动方式
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
height: 1000px;
}
button {
/* 固定按钮在视口的一个位置 */
position: fixed;
right: 10px;
bottom: 10px;
}
</style>
</head>
<body>
<button style="display: none;">返回</button>
<script>
// 获取元素
const btn = document.querySelector('button')
// 绑定滚动事件
window.addEventListener('scroll', function () {
// 获取页面高度
const n = document.documentElement.scrollTop
// 判断页面高度大于100px就显示按钮,否则就隐藏
if (n >=100) {
btn.style.display = 'block'
} else {
btn.style.display = 'none'
}
})
// 绑定点击事件
btn.addEventListener('click', function () {
// 设置滚动模式
scrollTo({
top:0,
style:'smooth'
})
})
</script>
</body>
</html>
瀑布流布局
要求: 多个等宽的图片进行穿插排序成六列,并且在目前显示的最后一张 图片显示之后,再进行下拉时能够在进行加载其他图片,每次下拉 显示20-30张图片。
解:1.先设置一个页面加载事件
2.设瀑布流函数
(1)获取子元素,视口宽度,再设置列数和容器宽度;
(2)把图片的高度放进一个数组中
(3)遍历数组找到高度最小的图片,将下一张放在其下方,最后更新高度
3.加载锁:防止滚动时重复触发加载
4.设置生成新图片的函数
5.绑定滚动事件
(1)获取容器距离顶部的距离,容器自身高度,视口高度;
(2)滚动至底部触发加载,用模拟异步加载
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
img {
width: 200px;
}
.box1 {
width: 100%;
position: relative;
margin: auto;
}
.box2 {
position: absolute;
float: left;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2">
<img src="./image/1.jpg" alt="">
</div>
<div class="box2">
<img src="./image/2.jpg" alt="">
</div>
<div class="box2">
<img src="./image/3.jpg" alt="">
</div>
<div class="box2">
<img src="./image/4.jpg" alt="">
</div>
<div class="box2">
<img src="./image/5.jpg" alt="">
</div>
<div class="box2">
<img src="./image/6.jpg" alt="">
</div>
<div class="box2">
<img src="./image/7.jpg" alt="">
</div>
<div class="box2">
<img src="./image/8.jpg" alt="">
</div>
<div class="box2">
<img src="./image/9.jpg" alt="">
</div>
<div class="box2">
<img src="./image/10.jpg" alt="">
</div>
<div class="box2">
<img src="./image/10.jpg" alt="">
</div>
<div class="box2">
<img src="./image/11.jpg" alt="">
</div>
<div class="box2">
<img src="./image/12.jpg" alt="">
</div>
<div class="box2">
<img src="./image/13.jpg" alt="">
</div>
<div class="box2">
<img src="./image/14.jpg" alt="">
</div>
<div class="box2">
<img src="./image/15.jpg" alt="">
</div>
<div class="box2">
<img src="./image/16.jpg" alt="">
</div>
<div class="box2">
<img src="./image/17.jpg" alt="">
</div>
<div class="box2">
<img src="./image/18.jpg" alt="">
</div>
<div class="box2">
<img src="./image/19.jpg" alt="">
</div>
<div class="box2">
<img src="./image/20.jpg" alt="">
</div>
<div class="box2">
<img src="./image/1.jpg" alt="">
</div>
<div class="box2">
<img src="./image/2.jpg" alt="">
</div>
<div class="box2">
<img src="./image/3.jpg" alt="">
</div>
<div class="box2">
<img src="./image/4.jpg" alt="">
</div>
<div class="box2">
<img src="./image/5.jpg" alt="">
</div>
<div class="box2">
<img src="./image/6.jpg" alt="">
</div>
<div class="box2">
<img src="./image/7.jpg" alt="">
</div>
<div class="box2">
<img src="./image/8.jpg" alt="">
</div>
<div class="box2">
<img src="./image/9.jpg" alt="">
</div>
<div class="box2">
<img src="./image/10.jpg" alt="">
</div>
<div class="box2">
<img src="./image/10.jpg" alt="">
</div>
<div class="box2">
<img src="./image/11.jpg" alt="">
</div>
<div class="box2">
<img src="./image/12.jpg" alt="">
</div>
<div class="box2">
<img src="./image/13.jpg" alt="">
</div>
<div class="box2">
<img src="./image/14.jpg" alt="">
</div>
<div class="box2">
<img src="./image/15.jpg" alt="">
</div>
<div class="box2">
<img src="./image/16.jpg" alt="">
</div>
<div class="box2">
<img src="./image/17.jpg" alt="">
</div>
<div class="box2">
<img src="./image/18.jpg" alt="">
</div>
<div class="box2">
<img src="./image/19.jpg" alt="">
</div>
<div class="box2">
<img src="./image/20.jpg" alt="">
</div>
</div>
<script>
// 页面加载完成事件(当页面加载完成,才执行大括号的回调函数)
// 必须要这样写,因为后面还要调用,绑定事件不好再调用
window.onload = function () {
waterFull()
}
function waterFull () {
// 获取函数
const box1 = document.querySelector('.box1')
const box2 = document.querySelectorAll('.box2')
// 单个子元素的宽度
let width = box2[0].offsetWidth
// 获取浏览器视口宽度
let clientWidth = document.documentElement.clientWidth
// 设置瀑布流的列数
let columnCount = 6
// 设置容器宽度:列数X子元素宽度
box1.style.width = width*columnCount + 'px'
// 创建一个空数组,储存每列的当前高度
let arr = []
for (let i = 0;i < box2.length; i++) {
// 第一行
if (i < columnCount) {
box2[i].style.top = '0px' // 第一行六个元素放在对应列的顶部
box2[i].style.left = i*width + 'px' // 实现瀑布流的一列一个,横向平铺
arr.push(box2[i].offsetHeight) // 在空数组增加第一行每列的高度
} else {// 第二排往后元素,放在"当前最矮列"的下方
// 找到数组里的最小值
let min = Math.min(...arr)
// 找到最小值的索引
let index = arr.indexOf(min)
// 把接下来的图片放在高度最小的图片下面
box2[i].style.top = min + 'px'
// 对齐高度最小的水平位置
box2[i].style.left = box2[index].offsetLeft + 'px'
// 更新该列的总高度
arr[index] += box2[i].offsetHeight
}
}
}
// 加载锁:防止滚动时重复触发加载
let isloading = false
// 生成更多图片的函数
function moreimage () {
// 创建一个空图片数组
let image = []
// 随机生成10-20个图片元素
for(let i = 1; i < Math.floor(Math.random() * 11) + 10; i++) {
// 创建一个指定的元素
let img = document.createElement('img')
// 图片路径
img.src = `./image/${i}.jpg`
// 给新图片添加图片的class
img.classList.add('box2')
// 添加图片到空图片数组里
image.push(img)
}
return image
}
// 滚动事件:判断是否到页面底部
window.addEventListener('scroll', function () {
const box1 =document.querySelector('.box1')
// 容器距离页面顶部的距离
let box1Top = box1.offsetTop
// 容器自身高度
let box1Height = box1.offsetHeight
// 视口高度
let clientHeight = document.documentElement.clientHeight
// 滚动到容器底部时触发加载
if (box1Height + box1Top - clientHeight <= 0 && !isloading) {
isloading =true // 锁定加载状态
// 模拟异步加载(加入图片,达到无限循环的效果)
setTimeout(function () {
// 生成新图片元素数组
let moreimages = moreimage()
const box1 = document.querySelector('.box1')
// 遍历数组,把图片加到容器中
moreimages.forEach(box2 => {box1.appendChild(box2)})
waterFull() // 重新布局瀑布流
isloading = false // 解锁加载状态
})
}
})
</script>
</body>
</html>
3.随机点名
要求: 分为上下两个部分,上方为显示区域,下方为控制区域。显示区域显示五十位群成员的学号和姓名,控制区域由开始和结束两个按钮 组成。点击开始按钮,显示区域里的内容开始滚动,点击结束按钮,内容滚动停止,随机显示一位成员的学号和姓名。
解:1.设置数组
(那个展示区好像是可以不用写的qwq)
2.存储定时器,用于后续清除
3.存储随机的学生索引
4.获取元素
5.绑定开始键的点击事件
(1)清除定时器;(2)启动定时器;(3)剩余一个学生的时候禁用button
5.绑定结束键的点击事件
(1)同上(1);(2)移除当前选中的学生(当数组中有学生时)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
h2 {
text-align: center;
}
.screen {
width: 500px;
height: 300px;
border: 1px solid black;
text-align: center;
align-content: center;
font-size: 36px;
margin: 0 auto;
}
.btns {
text-align: center;
margin-top: 10px;
}
button {
width: 100px;
}
</style>
</head>
<body>
<h2>随机点名</h2>
<div class="screen">学号 姓名</div>
<div class="btns">
<button class="start">开始</button>
<button class="end">结束</button>
</div>
<script>
// 设置数组
const arr = [
{
num: 1,
name: '灰太狼'
},
{
num: 2,
name: '红太狼'
},
{
num: 3,
name: '黄太狼'
},
{
num: 4,
name: '夜太狼'
},
{
num: 5,
name: '灰二太太狼'
},
{
num: 6,
name: '银太狼'
},
{
num: 7,
name: '白眼狼'
},
{
num: 8,
name: '拳击狼'
},
{
num: 9,
name: '武太狼'
},
{
num: 10,
name: '焦太狼'
},
{
num: 11,
name: '灰太狼'
},
{
num: 12,
name: '红太狼'
},
{
num: 13,
name: '黄太狼'
},
{
num: 14,
name: '夜太狼'
},
{
num: 15,
name: '灰二太太狼'
},
{
num: 16,
name: '银太狼'
},
{
num: 17,
name: '白眼狼'
},
{
num: 18,
name: '拳击狼'
},
{
num: 19,
name: '武太狼'
},
{
num: 20,
name: '焦太狼'
},
]
// 存储定时器ID,用于后续清除
let time = 0
// 存储随机选中的学生索引
let random = 0
// 获取元素
const screen = document.querySelector('.screen')
const start = document.querySelector('.start')
const end = document.querySelector('.end')
// 给start绑定点击事件
start.addEventListener('click', function () {
// 先清除之前的定时器(防止重复启动)
clearInterval(time)
// 启动定时器
time = setInterval(function () {
// 随机选中
random = parseInt(Math.random()*arr.length)
// 在screen上显示选中的学生信息
screen.innerHTML = `学号:${arr[random].num}
姓名:${arr[random].name}`
},100)
// 判断,若剩余最后一个学生则禁用开始键和结束键
if (arr.length === 1) {
start.disabled = end.disabled = true
}
})
// 给end绑定点击事件
end.addEventListener('click', function () {
// 清除之前的定时器
clearInterval(time)
// 如果数组有学生,就从数组中删除选中的学生
if (arr.length > 0) {
arr.splice(random, 1)
}
})
</script>
</body>
</html>
4.Tab选项卡
要求: 1.选项卡由英雄联盟、DOTA、风暴英雄、300英雄四块组成; 2.未选择时,默认选中第一个标签页;3.选择某一选项后,下方跳出对应游戏的相关介绍内容。
解:1.获取元素
2.遍历<a>标签
3.绑定鼠标移入事件
(1)取消导航栏当前激活的active;(2)给鼠标移入的a 添加active
(3)内容区同上(1)(2)【添加第 i+1 个.item】
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.tab {
width: 500px;
height: 300px;
margin: 20px;
border: 1px solid black;
}
.tab-nav {
width: 100%;
height: 60px;
line-height: 60px;
display: flex;
justify-content: space-between;
}
ul {
list-style: none;
display: flex;
/* margin-left: flex-end; */
}
li {
margin: 0 20px;
font-size: 14px;
}
a {
text-decoration: none;
/* border: 2px solid transparent; */
color: #333;
}
a.active {
/* border-color: #e1251b; */
color: #e1251b;
}
.content {
padding: 0 16px;
}
.item {
display: none;
}
.content .item.active {
display: block;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab-nav">
<ul>
<li><a href="javascript:;" class="active">英雄联盟</a></li>
<li><a href="javascript:;">DOTA</a></li>
<li><a href="javascript:;">风暴英雄</a></li>
<li><a href="javascript:;">300英雄</a></li>
</ul>
</div>
<div class="content">
<div class="item active">这是英雄联盟游戏</div>
<div class="item">这是DOTA游戏</div>
<div class="item">这是风暴英雄游戏</div>
<div class="item">这是300英雄游戏</div>
</div>
</div>
<script>
// 获取元素
const a = document.querySelectorAll('a')
for (let i = 0;i <a.length;i++) {
// 给a绑定鼠标移入事件
a[i].addEventListener('mouseenter', function () {
// 取消导航栏当前激活的active(移除'active'类)
document.querySelector('.tab-nav .active').classList.remove('active')
// 给鼠标移入的a添加active
this.classList.add('active')
// 取消内容区当前激活的active(移除'active'类)
document.querySelector('.content .active').classList.remove('active')
// 给内容区中第i+1个.item,添加active(显示当前标签)
document.querySelector(`.content .item:nth-child(${i + 1})`).classList.add('active')
})
}
</script>
</body>
</html>
动态表格
要求:
1.表格由专业班级学号1-10号同学的信息组成,包括:学号、姓 名、性别、二级学院、班级、专业、辅导员;
2.表格的奇数行字体为黑色,底色为白色;偶数行字体为白色,底 色为黑色;
3.表格的每一行后有一个删除按钮,点击后会跳出提示弹窗,确认后删除该行的内容,并且删除后上述的颜色规律保持不变:
4.表格的右上方有一个添加按钮,点击后跳出一个表单弹窗,可以填加新的学生的信息。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
position: relative;
}
table {
border-spacing: 0;
}
td,th {
border: 1px solid black;
width: 150px;
text-align: center;
}
a {
cursor: pointer;
text-decoration: none;
color: inherit;
}
.box tbody tr:nth-child(2n) {
color: white;
background-color: black;
}
.box tbody tr:nth-child(2n-1) {
color: black;
background-color: white;
}
button {
display: inline-block;
width: 80px;
line-height: 24px;
position: fixed;
right: 20px;
}
.box1 {
width: 100%;
height: 30px;
}
.box input {
display: inline-block;
width: 150px;
height: 20px;
border: none;
text-align: center;
font-size: 16px;
background-color: inherit;
color: inherit;
}
</style>
</head>
<body>
<form action="" id="addFrom">
<div class="box">
<div class="box1">
<table>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>性别</th>
<th>二级学院</th>
<th>班级</th>
<th>专业</th>
<th>辅导员</th>
<th>删除</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<button>添加</button>
</div>
</div>
</form>
<script>
window.addEventListener('load', function () {
let content = [
{
num: 1,
name: "灰太狼",
gender: "男",
school: "计算机工程学院",
class: "3",
subject: "计算机科学与技术",
teacher: "xxx"
},
{
num: 2,
name: "红太狼",
gender: "女",
school: "计算机工程学院",
class: "1",
subject: "软件工程",
teacher: "xxx"
},
{
num: 3,
name: "喜羊羊",
gender: "男",
school: "通信工程学院",
class: "5",
subject: "通信工程",
teacher: "xxx"
},
{
num: 4,
name: "美羊羊",
gender: "女",
school: "电气工程学院",
class: "1",
subject: "计算机科学与技术",
teacher: "xxx"
},
{
num: 5,
name: "懒洋洋",
gender: "男",
school: "计算机工程学院",
class: "3",
subject: "计算机科学与技术",
teacher: "xxx"
},
{
num: 6,
name: "灰太狼",
gender: "男",
school: "计算机工程学院",
class: "3",
subject: "计算机科学与技术",
teacher: "xxx"
},
{
num: 7,
name: "红太狼",
gender: "女",
school: "计算机工程学院",
class: "1",
subject: "软件工程",
teacher: "xxx"
},
{
num: 8,
name: "喜羊羊",
gender: "男",
school: "通信工程学院",
class: "5",
subject: "通信工程",
teacher: "xxx"
},
{
num: 9,
name: "美羊羊",
gender: "女",
school: "电气工程学院",
class: "1",
subject: "计算机科学与技术",
teacher: "xxx"
},
{
num: 10,
name: "懒洋洋",
gender: "男",
school: "计算机工程学院",
class: "3",
subject: "计算机科学与技术",
teacher: "xxx"
}
]
const tbody = document.querySelector('tbody')
const btn = document.querySelector('button')
for (let i = 0;i< content.length; i++) {
const tr = document.createElement('tr')
tr.innerHTML = `
<td>${content[i].num}</td>
<td>${content[i].name}</td>
<td>${content[i].gender}</td>
<td>${content[i].school}</td>
<td>${content[i].class}</td>
<td>${content[i].subject}</td>
<td>${content[i].teacher}</td>
<td>
<a href="javascript:" data-id=${i}>删除</a>
</td>
`
tbody.appendChild(tr)
}
const a = document.querySelectorAll('a')
for (let i = 0; i < a.length;i++) {
a[i].addEventListener('click', function () {
alert('你确定要删除吗?')
tbody.removeChild(this.parentNode.parentNode)
})
}
btn.addEventListener('click', function (e) {
e.preventDefault()
const tr = document.createElement('tr')
tbody.appendChild(tr)
for (let k in content[1]) {
const td = document.createElement("td")
td.innerHTML = `<input type="text">`
tr.appendChild(td)
}
const td = document.createElement('td')
td.innerHTML = `<a href="#">删除</a>`
tr.appendChild(td)
const a = document.querySelectorAll('a')
for (let i = 0; i < a.length; i++) {
a[i].addEventListener('click', function () {
alert('你确定要删除吗?')
tbody.removeChild(this.parentNode.parentNode)
})
}
})
})
</script>
</body>
</html>
6.电子时钟的时间需与北京时间实时对应。
解:1.获取元素
2.定义时间更新函数
(1)创建Date对象;(2)得到当前时间;(3)个位数补零;(4)渲染给页面
3.页面加载后立即执行(初始化)
4.定时更新
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
display: flex;
}
.box1 {
display: flex;
width: 200px;
height: 200px;
border: 1px solid black;
font-size: 150px;
justify-content: center;
align-items: center;
}
.mask {
font-size: 150px;
display: flex;
margin-top: -20px;
}
</style>
</head>
<body>
<div class="box1" id="h"></div>
<div class="mask">:</div>
<div class="box1" id="m"></div>
<div class="mask">:</div>
<div class="box1" id="s"></div>
<script>
// 获取元素
const hour = document.querySelector('#h')
const min = document.querySelector('#m')
const sec = document.querySelector('#s')
// 定义时间更新函数
function getNowTime() {
let date = new Date() // 创建Date对象,获取当前系统的时间
let h = date.getHours() // 得到当前小时
let m = date.getMinutes() // 得到当前分钟
let s = date.getSeconds() // 得到当前秒
// 个位数前补0
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s
// 渲染给页面
hour.innerHTML = h
min.innerHTML = m
sec.innerHTML = s
}
getNowTime() // 页面加载后立即执行,确保打开页面就显示当前时间
setInterval(getNowTime, 1000) // 定时更新
</script>
</body>
</html>
7.表单验证码
1.表单需包含昵称、姓名、QQ、手机号、邮箱、密码、确认密码以 发送验证码及提交和重置按钮;
2.点击表单里的输入框,隐藏提示文字;
3.点击提交和重置按钮时,都需要有相应的提示;
4.在表单提交是,需要进行验证验证填写内容是否合理:昵称不超 过10个字、姓名不超过4个字、QQ号为长度小于等于10大于5位的数字、手机号为长度11位的数字、密码由字母和数字组成且大于8位小于16位、密码和确认密码需相同。
5.发送验证码按钮点击后,会被禁用;发送验证码按钮被点击后,按钮里面的内容会变化成1分钟的倒计时;待发送验证码按钮被触发后才可以点击提交按钮,需在验证码框里填写 0505,用弹窗提示成功。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="card">
<form class="form">
<div data-prop="username" class="form-item">
<span class="zhanghao1"></span>
<input type="text" name="username" placeholder="设置昵称">
<span class="msg"></span>
</div>
<div data-prop="realname" class="form-item">
<span class="realname1"></span>
<input type="text" name="realname" placeholder="输入真实姓名">
<span class="msg"></span>
</div>
<div data-prop="QQ" class="form-item">
<span class="QQ1"></span>
<input type="text" name="QQ" placeholder="QQ号">
<span class="msg"></span>
</div>
<div data-prop="phone" class="form-item">
<span class="phone1"></span>
<input type="text" name="phone" placeholder="输入手机号码">
<span class="msg"></span>
</div>
<div data-prop="email" class="form-item">
<span class="email1"></span>
<input type="text" name="email" placeholder="输入邮箱">
<span class="msg"></span>
</div>
<div data-prop="password" class="form-item">
<span class="password1"></span>
<input type="password" name="password" placeholder="设置密码">
<span class="msg"></span>
</div>
<div data-prop="confirm" class="form-item">
<span class="confirm1"></span>
<input type="password" name="confirm" placeholder="确认密码">
<span class="msg"></span>
</div>
<div data-prop="code" class="form-item">
<span class="code1"></span>
<input type="text" name="code" placeholder="短信验证码">
<span class="msg"></span>
<button id="getcode">发送验证码</button>
</div>
<button class="submit">提交</button>
<button class="again">重置</button>
</form>
</div>
</div>
<script>
// 获取元素
const inp = document.querySelectorAll('input')
const submit = document.querySelector('.submit')
const again = document.querySelector('.again')
// username
const username =document.querySelector('[name=username]')
// 绑定change事件(失去焦点且内容发生改变的)
username.addEventListener('change', verifyUserName)
function verifyUserName() {
// 获取输入框的下一个兄弟元素(用来展示错误提示的<span>)
const span = username.nextElementSibling
// 定义正则规则:匹配"1~10个任意字符"
const reg = /^.{1,10}$/
// 校验输入值:不满足规则
if (!reg.test(username.value)) {
span.innerText = '昵称不超过10个字' // 显示错误提示
return false // 表示验证不通过
}
else {
span.innerText = '' // 清空提示
return true // 表示验证通过
}
}
// realname
const realname =document.querySelector('[name=realname]')
realname.addEventListener('change', verifyRealName)
function verifyRealName() {
const span = realname.nextElementSibling
const reg = /^.{1,4}$/
if (!reg.test(realname.value)) {
span.innerText = '姓名不超过4个字'
return false
}
else {
span.innerText = ''
return true
}
}
const QQ = document.querySelector('[name=QQ]')
QQ.addEventListener('change', verifyQQ)
function verifyQQ() {
const span = QQ.nextElementSibling
const reg = /^\d{6,10}$/
if(!reg.test(QQ.value)) {
span.innerText = '长度小于等于10大于5位的数字'
return false
}
span.innerText = ''
return true
}
// Phone
const phone = document.querySelector('[name=phone]')
phone.addEventListener('change', verifyPhone)
function verifyPhone() {
const span = phone.nextElementSibling
const reg = /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/
if(!reg.test(phone.value)) {
span.innerText = '请输入正确的11位手机号码'
return false
}
span.innerText = ''
return true
}
// password
const password = document.querySelector('[name=password]')
password.addEventListener('change', verifyPwd)
function verifyPwd() {
const span = password.nextElementSibling
const reg = /^[a-zA-Z0-9-_]{9,16}$/
if(!reg.test(password.value)) {
span.innerText = '密码由字母和数字组成且大于8位小于16位'
return false
}
span.innerText = ''
return true
}
// 输入框点击交互
inp.forEach(function(input) {
input.addEventListener('click',function () {
this.placeholder = '' // 用户点击输入框时,清空该输入框的placeholder
})
})
// 表单重置按钮
again.addEventListener('click', function () {
alert('您确定要重置吗?')
inp.forEach(function (input) {
input.value = ''
})
})
// 表单提交按钮
submit.addEventListener('click', function () {
alert('您确定要提交吗?')
const inpCode = document.querySelector('[name=code]')
// 除去内容前后空格
const inpValue = inpCode.value.trim()
// 校验验证码是否是"0505"
if(inpValue !== "0505") {
alert('请输入正确的验证码')
}
else {
alert('成功')
}
Pass () // 调用密码一致性校验函数
// 清空所有输入框
inp.forEach(function(input) {
input.value = ''
})
})
let flag = true // 控制验证码按钮是否可点击的标记
const code = document.querySelector('#getcode')
code.addEventListener('click', function (e) {
e.preventDefault() // 阻止按钮默认行为
if(flag) {
// 倒计时开始,标记为"不可点击"
flag =false
let i = 60
code.innerHTML = `${i}秒后重新获取`
// 启动定时器,每一秒执行一次
let timerId = setInterval(function () {
i--
code.innerHTML = `${i}秒后重新获取`
// 倒计时结束
if (i === 0) {
clearInterval(timerId) // 清除定时器
code.innerHTML = `重新获取`
flag = true // 标记为可点击
}
}, 1000)
}
})
function Pass () {
// 获取元素
const password = document.querySelector('[name=password]').value
const confirm = document.querySelector('[name=confirm]').value
// 校验两次输入的密码是否一致
if(password !== confirm) {
alert('两次密码输入不一致,请再次输入')
return false
}
else {
return true
}
}
</script>
</body>
</html>
8.滚动弹幕
1.页面上漂浮字体大小不一、颜色不一,从左向右滚动的弹幕;
2.底部中间有一个发送功能,可以发送新的弹幕;
3.底部的发送部分可以向下收起和弹出。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.view {
position: relative;
width: 100%;
height: 400px;
border: 1px solid black;
}
.page {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: rgb(139, 139, 139);
padding: 10px;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease;
}
.inner {
width: 300px;
padding: 5px;
margin-right: 10px;
}
.send {
padding: 5px 10px;
}
.up {
position: absolute;
bottom: 10px;
left: 10px;
}
</style>
</head>
<body>
<div class="view"></div>
<div class="page">
<input type="text" placeholder="输入弹幕" class="inner">
<button class="send">发送</button>
</div>
<button class="up">收起/弹出</button>
<script>
// 获取元素
const view = document.querySelector('.view')
const page = document.querySelector('.page')
const inner = document.querySelector('.inner')
const send = document.querySelector('.send')
const up = document.querySelector('.up')
// 用于记录 "输入框是否被隐藏" 的状态 ------ 初始时输入框是显示的
let isInputHidden = false
// 创建并返回一个包含该文本的弹幕 DOM 元素
function createDanmuElement(text) {
const danmu = document.createElement('div')
danmu.textContent = text // 文本内容
danmu.style.position = 'absolute' // 文本定位
danmu.style.left = '-200px' // 弹幕进入
// 高度随机
danmu.style.top = Math.floor(Math.random() * (view.clientHeight - 30)) + 'px'
// 颜色随机
danmu.style.color = `rgb({Math.floor(Math.random() \* 256)}, {Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)})`
// 大小随机
danmu.style.fontSize = Math.floor(Math.random() * 20) + 12 + 'px'
danmu.style.whiteSpace = 'nowrap' // 弹幕不换行
view.appendChild(danmu) // 添加在后面
return danmu
}
function moveDanmu(danmu) {
// 弹幕初始位置
let left = -200
// 随机速度
const speed = Math.floor(Math.random() * 3) + 1
// 启动定时器:从左到右
const Timer = setInterval(() => {
left += speed // 右移动
danmu.style.left = left + 'px' // 设置弹幕的水平位置
// 当弹幕完全离开视图右侧
if (left > view.clientWidth) {
clearInterval(Timer) // 清除定时器
view.removeChild(danmu) // 清除弹幕
}
}, 10)
}
// 传输弹幕
send.addEventListener('click', function () {
const text = inner.value
// 创建弹幕DOM元素
const danmu1 = createDanmuElement(text)
moveDanmu(danmu1) // 让新创建的弹幕开始移动
inner.value = '' // 清空输入框
})
up.addEventListener('click', function () {
// 切换隐藏状态
isInputHidden =! isInputHidden
if (isInputHidden) {
page.classList.add('hidden') // 给输入区域添加隐藏类
up.textContent = '弹出' // 按钮文字改为弹出
}
else {
page.classList.remove('hidden') // 移除隐藏类,显示输入区域
up.textContent = '收起' // 按钮文字改为收起
}
})
// 弹幕
for (let i = 0; i < 10; i++) {
const text = `我一定会回来的`
const danmu = createDanmuElement(text)
moveDanmu(danmu)
}
</script>
</body>
</html>
1.鼠标移至图片上方,鼠标周围出现黄色的的正方形框,黄色矩形 框会随着鼠标的移动而移动;2.将黄色正方形框里的内容的长和宽均放大2.4倍,并在图片右边进行显示。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.small {
width: 450px;
height: 450px;
border: 1px solid #ccc;
float: left;
position: relative;
margin: 10px;
}
.big {
width: 450px;
height: 450px;
overflow: hidden;
position: relative;
display: none;
}
.mask {
width: 150px;
height: 150px;
background-color: yellow;
position: absolute;
top: 0px;
left: 0px;
opacity: .5;
cursor: move;
display: none;
}
.image {
position: absolute;
width: 450px;
height: 450px;
top: 0px;
left: 0px;
}
.img {
position: absolute;
top: 0px;
left: 0px;
}
</style>
</head>
<body>
<!-- 小图容器 -->
<div class="small">
<img src="./img/course12.png" alt="" class="image">
<!-- 透明图 -->
<div class="mask"></div>
</div>
<!-- 大图容器 -->
<div class="big">
<img src="./img/course12.png" alt="" class="img">
</div>
<script>
// 获取元素
const mask = document.querySelector('.mask')
const small = document.querySelector('.small')
const big = document.querySelector('.big')
const img = document.querySelector('.img')
const smallImg = document.querySelector('.image')
const ZOOM_SCALE = 2.4 // 放大倍数(大图是小图的2.4倍)
// 鼠标进入显示
small.addEventListener('mouseenter', function () {
mask.style.display = 'block'
big.style.display = 'block'
})
// 鼠标离开隐藏
small.addEventListener('mouseleave', function () {
mask.style.display = 'none'
big.style.display = 'none'
})
// 鼠标移动获取位置
small.addEventListener('mousemove', function (e) {
// 计算鼠标在小图容器内的相对位置
let x = e.pageX - this.offsetLeft // 鼠标相当于文档的位置
let y = e.pageY - this.offsetTop
// 让鼠标位于遮挡层中心
let maskX = x - mask.offsetWidth / 2
let maskY = y - mask.offsetHeight / 2
// 限制鼠标遮挡成不超过小图容器
let maskWidth = small.offsetWidth - mask.offsetWidth
let maskHeight = small.offsetHeight - mask.offsetHeight
if (maskX <= 0) {
maskX = 0
}else if (maskX >= maskWidth) {
maskX = maskWidth
}
if (maskY <= 0) {
maskY = 0
}else if (maskY >= maskHeight) {
maskY = maskHeight
}
// 设置者当场位置
mask.style.left = maskX + 'px'
mask.style.top = maskY + 'px'
// 技术按大图的反向移动距离
// 大图移动距离 = 遮罩位置 X (大图尺寸 - 大图容器尺寸) / (小图尺寸 - 遮罩尺寸)
let imgWidth = img.offsetWidth - small.offsetWidth
let imgHeight = img.offsetHeight - small.offsetHeight
let bigX = maskX * imgWidth / maskWidth;
let bigY = maskY * imgHeight / maskHeight;
// 移动大图(反向偏移,实现"跟随放大")
img.style.left = (-bigX) + 'px';
img.style.top = (-bigY) + 'px';
})
// 初始化大图尺寸
function initZoomSize() {
const smallImg = document.querySelector('.image');
const smallWidth = small.offsetWidth;
const smallHeight = small.offsetHeight;
// 设置大图尺寸为小图的2.4倍
img.style.width = (smallWidth * ZOOM_SCALE) + 'px';
img.style.height = (smallHeight * ZOOM_SCALE) + 'px';
}
</script>
</body>
</html>
11.省市区三级联动
通过三个下拉菜单的联动来实现,第一级下拉菜单为省级,第二级 下拉菜单为市级,第三级下拉菜单为区级。当点击第一级下拉菜 单,第二级菜单的内容会自动匹配;选择第二级菜单时,第三级菜单会自动生成。当我取消上一级菜单的选项时,次一级选项会自动消失。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 三个下拉框 -->
<select name="" id="province">
<option value="">请选择省份</option>
</select>
<select name="" id="city">
<option value="">请选择城市</option>
</select>
<select name="" id="area">
<option value="">请选择区县</option>
</select>
<script>
// 数据定义:
const provinces = ['福建','江苏','河北']
const cities = [
'漳州市', '厦门市'\], \['南京市', '苏州市'\], \['石家庄市', '秦皇岛市'
]
const areas = [
\['芗城区','龙文区'\], \['思明区','同安区'\]\], \[\['玄武区','秦淮区'\], \['姑苏区','吴中区'\]\], \[\['桥西区','新华区'\], \['海港区','山海关区'\]
]
// 获取DOM元素
const provinceSelect = document.querySelector('#province')
const citySelect = document.querySelector('#city')
const areaSelect = document.querySelector('#area')
//动态填充选项函数
function creatOptions(select, data) {
select .options.length = 1 // 清空原有选项
data.forEach((item, index) => {
// 将新选项添加到下拉框中
select.options.add(new Option(item, index))
})
}
// 初始化省份下拉框
creatOptions(provinceSelect, provinces)
// 省份变化时,联动城市下拉
provinceSelect.onchange = function () {
const provinceIndex = this.value
if (provinceIndex >= 0) {
creatOptions(citySelect, cities[provinceIndex]);
areaSelect.options.length = 1 // 清空区域选项
}
}
// 城市变化时,联动区县下拉
citySelect.onchange = function () {
const provinceIndex = provinceSelect.value
const cityIndex = this.value
if (cityIndex >= 0) {
creatOptions(areaSelect, areas[provinceIndex][cityIndex]);
}
}
</script>
</body>
</html>
12.轮播图
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
box-sizing: border-box;
}
.box1 {
width: 560px;
height: 400px;
overflow: hidden;
}
.box2 {
width: 100%;
height: 320px;
}
img {
width: 100%;
height: 100%;
display: block;
}
.box3 {
height: 80px;
background-color: rgb(100.67,68);
padding: 12px 12px 0 12px;
position: relative;
}
.btn {
position: absolute;
right: 0;
top: 12px;
display: flex;
}
button {
margin-right: 12px;
width: 28px;
height: 28px;
appearance: none;
border: none;
background-color: rgba(255,255,255,0.1);
color: #fff;
border-radius: 4px;
cursor: pointer;
}
.next,.prev {
opacity: 0;
}
.box1:hover .next {
opacity: 1;
}
.box1:hover .prev {
opacity: 1;
}
.box3 .btn button:hover {
background-color: rgba(255,255,255,0.2);
}
p {
margin: 0;
color: #fff;
font-size: 18px;
margin-bottom: 10px;
}
.indicator {
margin: 0;
padding: 0;
list-style: none;
display: flex;
align-items: center;
}
.indicator li {
width: 8px;
height: 8px;
margin: 4px;
border-radius: 50%;
background: #fff;
opacity: 0.4;
cursor: pointer;
}
.indicator li.active {
width: 12px;
height: 12px;
opacity: 1;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2">
<img src="./image/1.jpg" alt="">
</div>
<div class="box3">
<p>11111</p>
<ul class="indicator">
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="btn">
<button class="prev"><</button>
<button class="next">></button>
</div>
</div>
</div>
</body>
<script>
// 轮播数据源定义
const data = [
{ url: './image/1.jpg', title: '111', color: 'green' },
{ url: './image/2.jpg', title: '222', color: 'yellow' },
{ url: './image/3.jpg', title: '333', color: 'blue' },
{ url: './image/4.jpg', title: '444', color: 'pink' },
{ url: './image/5.jpg', title: '555', color: 'red' },
{ url: './image/6.jpg', title: '666', color: 'brown'},
{ url: './image/7.jpg', title: '777', color: 'grey' },
{ url: './image/8.jpg', title: '888', color: 'skyblue' }
]
const img = document.querySelector('img')
const p = document.querySelector('p')
const box3 = document.querySelector('.box3')
const next = document.querySelector('.next')
const prev = document.querySelector('.prev')
let i = 0
// 下一张按钮点击事件
next.addEventListener('click', function() {
// 索引+1,切换到下一项
i++
// 边界判断:超过最后一项(索引7),重置为第一项(索引0)
if(i >=8) {
i+8
}
// 调用更新函数,同步渲染轮播内容
btn()
})
// 上一张按钮点击事件
prev.addEventListener('click', function () {
i--
// 边界判断:小于第一项(索引0),重置为最后一项(索引7)
if (i < 0) {
i =7
}
btn()
})
function btn() {
img.src = data[i].url// 更新轮播图片路径
p.innerHTML = data[i].title// 更新标题文本
box3.style.backgroundColor = data[i].color// 更新box3背景色
// 指示器高亮切换:先移除原有的active,再给当前项加active
document.querySelector('.indicator .active').classList.remove('active')
document.querySelector(`.indicator li:nth-child(${i + 1})`).classList.add('active')
}
// 自动轮播:定时实现
let time = setInterval(function () {
next.click()
},1000)
const box1 = document.querySelector('.box1')
// 鼠标进入
box1.addEventListener('mouseenter', function () {
clearInterval(time)// 清除定时器,暂停轮播
})
// 鼠标离开
box1.addEventListener('mouseleave', function () {
clearInterval(time)// 先清除旧定时器
time = setInterval(function () {// 重新创建定时器,恢复轮播
next.click()
},1000)
})
</script>
</html>