上述HTML代码创建了一个简单的网页,其中包含一个可以在页面内自动移动的小方块(div
元素),并且当鼠标悬停在该方块上时,动画会暂停;当鼠标移开时,动画会继续。以下是代码的详细分析:
HTML结构
<head>
部分设置了文档的字符编码为UTF-8,视口宽度适应设备宽度,并定义了一些基本的样式和一个标题。<body>
部分包含一个div
元素,其ID为notice
,内部包含一个链接(<a>
标签),虽然链接地址设置为#
(代表无实际跳转),但可以在后续通过JavaScript或手动更改为有效的URL。
CSS样式
body
的背景色被设置为浅灰色(#e9e9e9
)。#notice
的样式定义包括:- 绝对定位(
position: absolute;
),这意味着它的位置将相对于最近的已定位祖先元素(如果没有,则是<html>
)。 - 宽度和高度均为120px。
- 背景色为鲜红色(
rgb(233, 21, 21)
)。 - 文本水平和垂直居中(通过
line-height
和text-align
)。
- 绝对定位(
JavaScript功能
- 变量初始化 :
notice
:获取ID为notice
的div
元素。xSpeed
和ySpeed
:设置方块在x轴和y轴上的移动速度。animationFrameId
:用于存储动画帧的ID,以便可以暂停和继续动画。width
和height
:计算浏览器视口的宽度和高度,确保方块不会移出可视区域。
- 动画函数
run()
:- 使用
getBoundingClientRect()
获取方块当前的位置。 - 计算方块下一帧的位置(
newX
和newY
)。 - 检查是否达到视口的边界,如果是,则反转移动方向。
- 更新方块的
left
和top
样式以移动方块。 - 使用
requestAnimationFrame(run)
递归调用run()
,以创建连续的动画效果。
- 使用
- 鼠标事件监听 :
mouseenter
事件:当鼠标悬停在方块上时,调用cancelAnimationFrame(animationFrameId)
来暂停动画。mouseleave
事件:当鼠标从方块上移开时,重新调用run()
来继续动画。
功能总结
- 页面加载后,一个红色的小方块会在浏览器窗口内自动移动,碰到边界时会反弹。
- 当用户将鼠标悬停在方块上时,动画会暂停;移开鼠标后,动画会继续。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
body {
background-color: #e9e9e9;
}
#notice {
position: absolute;
width: 120px;
height: 120px;
background-color: rgb(233, 21, 21);
line-height: 120px;
text-align: center;
}
</style>
<title>Auto Text Effect</title>
</head>
<body>
<div id="notice"> <!-- 修正了这里的空格字符 -->
<a href="#" target="_blank">红包!速点!</a> <!-- 修正了链接中的空格字符,并添加了一个实际的链接地址 # -->
</div>
<script>
let notice = document.getElementById('notice');
let xSpeed = 4; // x轴方向移动的速度
let ySpeed = 2.4; // y轴方向移动的速度(类似于向量)
let animationFrameId;
// 兼容性的浏览器视口高度和宽度
let width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
let height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// 动画运行函数
function run() {
let rect = notice.getBoundingClientRect(); // 返回盒子的位置对象信息
// 下一瞬/帧 要修改盒子的left或top的值,等于当前位置加速度
let newX = rect.left + xSpeed;
let newY = rect.top + ySpeed;
// 位置判断,到达边界,碰撞更改
if (newX + notice.offsetWidth >= width) {
console.log('到达右边界');
newX = width - notice.offsetWidth; // 右边界位置是视口宽度去除自身宽度
xSpeed = -xSpeed; // 移动方向颠倒过来
} else if (newX <= 0) {
console.log('到达左边界');
newX = 0; // 左边界位置是起始位置是0
xSpeed = -xSpeed; // 移动方向颠倒过来
}
// Y轴同理不赘述
if (newY + notice.offsetHeight >= height) {
console.log('到达下边界');
newY = height - notice.offsetHeight;
ySpeed = -ySpeed;
} else if (newY <= 0) {
console.log('到达上边界');
newY = 0;
ySpeed = -ySpeed;
}
// 更改位置即为移动dom元素
notice.style.left = `${newX}px`;
notice.style.top = `${newY}px`;
// 再次run
animationFrameId = requestAnimationFrame(run);
}
// 开始动画
run();
/**
* 添加事件监听器,使用mouseenter和mouseleave
* 即为鼠标hover效果
* */
notice.addEventListener('mouseenter', () => {
console.log('移入暂停');
cancelAnimationFrame(animationFrameId); // 取消动画帧
});
notice.addEventListener('mouseleave', () => {
console.log('移出继续');
run();
});
</script>
</body>
</html>