在GPT回答问题的页面上,有一个小黑点会根据回答的内容一直跟随文本移动的一个效果。这种动画效果不仅使用户体验更加生动和直观,还增强了页面的互动性和吸引力。本文将详细介绍如何使用HTML、CSS和JavaScript来实现这个光标跟随文本动画效果的技术细节和实现过程。
1. 概述
光标跟随文本动画效果是指在文本逐步显示的过程中,光标(或其他自定义标记)会实时跟随文本内容移动,仿佛在输入的同时显示文本。这种效果常用于模拟打字机效果或增强页面的交互性。
2. HTML 结构
首先,我们来看一下HTML部分的结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>光标跟随效果</title>
<style>
/* CSS 样式在这里定义 */
</style>
</head>
<body>
<div class="content-box">
<div class="text"></div>
<div class="dot"></div>
</div>
<!-- JavaScript 部分在这里 -->
</body>
</html>
在这段HTML代码中,我们定义了一个.content-box容器,包含两个子元素:.text用于显示逐步展示的文本内容,.dot则是模拟光标的元素。
3. CSS 样式
接下来,我们为元素添加CSS样式,使其具有合适的布局和外观:
<style>
.content-box {
position: relative;
}
.text {
background-color: #ccc;
width: fit-content;
padding: 5px;
border-radius: 0 10px 10px 10px;
}
.dot {
width: 10px;
height: 10px;
border-radius: 5px;
background-color: black;
position: absolute;
top: 5px;
animation: dotAnimation 0.5s infinite;
}
@keyframes dotAnimation {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>
在这段CSS中,定义了.content-box容器的基本样式,包括背景色和边框圆角。.dot元素是一个黑色圆点,通过position: absolute;将其定位在.text元素的上方,并且通过CSS动画dotAnimation使其产生闪烁效果。
4. JavaScript 动态效果
最后,我们使用JavaScript来实现光标跟随文本动画的核心逻辑:
<script>
const dot = document.querySelector('.dot'); // 获取光标元素
const ctBox = document.querySelector('.content-box'); // 包含文本和光标的容器
const txt = document.querySelector('.text'); // 文本内容的容器
//定义一段文字
const characters = `北国风光,千里冰封,万里雪飘。
望长城内外,惟余莽莽;大河上下,顿失滔滔。
山舞银蛇,原驰蜡象,欲与天公试比高。
须晴日,看红装素裹,分外妖娆。
江山如此多娇,引无数英雄竞折腰。
惜秦皇汉武,略输文采;唐宗宋祖,稍逊风骚。
一代天骄,成吉思汗,只识弯弓射大雕。
俱往矣,数风流人物,还看今朝。`; // 要显示的文本
// 延时函数
function delay(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time);
});
}
// 格式化文本为段落格式
function formatText(text) {
return text.split('\n').map(e => `<p>${e}</p>`).join('');
}
// 获取最后一个文本节点
function getLastText(node) {
if (node.nodeType === Node.TEXT_NODE) {
return node;
}
for (let i = node.childNodes.length - 1; i >= 0; i--) {
let child = node.childNodes[i];
let result = getLastText(child);
if (result) {
return result;
}
}
return null;
}
// 开始显示文本
async function start(delayTime) {
for (let i = 0; i < characters.length; i++) {
let content = characters.slice(0, i); // 逐步获取文本内容
let result = formatText(content); // 格式化为段落格式
txt.innerHTML = result; // 更新文本内容显示
updateView(); // 更新光标位置
await delay(delayTime); // 等待一段时间
if (i == charactes.length - 1) {
dot.remove();
}
}
}
// 更新光标位置
function updateView() {
let textNode = getLastText(txt); // 获取最后一个文本节点
let tempNode = document.createTextNode('|'); // 创建一个临时文本节点表示光标位置
if (textNode) {
textNode.after(tempNode); // 插入临时节点在最后一个文本节点后
} else {
txt.appendChild(tempNode); // 如果没有文本节点,则直接添加
}
const range = document.createRange(); // 创建一个新的文本范围对象
range.setStart(tempNode, 0); // 设置范围的起始位置为临时节点的开头
range.setEnd(tempNode, 0); // 设置范围的结束位置为临时节点的开头(即光标位置)
const rect = range.getBoundingClientRect(); // 获取新范围的边界位置信息
const textContainer = ctBox.getBoundingClientRect(); // 获取文本容器的边界位置信息
let left = rect.left - textContainer.left; // 计算光标的水平位置
let top = rect.top - textContainer.top; // 计算光标的垂直位置
dot.style.transform = `translate(${left}px,${top}px)`; // 设置光标的位置
tempNode.remove(); // 移除临时节点
}
start(100); // 调用开始函数,每100毫秒显示一个字符
</script>
在这段JavaScript代码中,首先获取需要操作的DOM元素,包括文本容器.text、光标.dot以及包含它们的容器.content-box。然后,通过start()函数逐步显示定义的characters文本内容,并在每个字符显示后调用updateView()函数更新光标的位置。
5. 总结
通过结合HTML、CSS和JavaScript,成功实现了一个光标跟随文本动画效果。这种效果不仅增加了页面的视觉吸引力,还提升了用户与页面的交互性。你可以根据实际需求,进一步优化和扩展这个效果,例如增加更复杂的动画效果或改进文本显示方式。
通过本文的学习,希望你能够掌握如何利用前端技术实现类似的动态效果,为自己的Web项目增添更多创意和互动性。