目录
一、交互组件类
轮播图实现
Tab切换功能
模态框 (Modal)
下拉菜单
手风琴效果
自定义右键菜单
二、表单处理类
表单验证增强
密码强度检测(输入安全相关)
三、数据存储类
本地存储记忆功能(localStorage/cookie操作)
四、动态内容处理
实时搜索过滤
动态加载更多内容
随机名言生成器
五、实用工具类
网页计时器/倒计时
复制到剪贴板
简易画板功能(图形交互工具)
六、用户体验优化
回到顶部按钮
图片懒加载(性能优化)
原生js图片放大镜效果
暗黑模式切换
网页主题色切换
七、视觉效果类
点击切换图片(基础视觉交互)
滚动动画触发
视差滚动效果
除了以下功能,还想要什么功能可写评论,作者大大看到就会回复哦
一、交互组件类
轮播图实现
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>轮播图示例</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="carousel">



<!-- 可以继续添加更多图片 -->
<div class="controls">
<button id="prev">Prev</button>
<button id="next">Next</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>

styles.css
.carousel {
position: relative;
width: 600px;
height: 400px;
overflow: hidden;
margin: 0 auto;
border: 2px solid #ddd;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.carousel img {
width: 100%;
height: 100%;
display: none;
transition: opacity 0.5s ease;
}
.carousel img.active {
display: block;
opacity: 1;
}
.controls {
position: absolute;
top: 50%;
width: 100%;
display: flex;
justify-content: space-between;
transform: translateY(-50%);
}
.controls button {
background-color: rgba(0, 0, 0, 0.5);
color: white;
border: none;
padding: 10px;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s ease;
}
.controls button:hover {
background-color: rgba(0, 0, 0, 0.7);
}

script.js
document.addEventListener('DOMContentLoaded', () => {
let currentIndex = 0;
const images = document.querySelectorAll('.carousel img');
const prevButton = document.getElementById('prev');
const nextButton = document.getElementById('next');
function showImage(index) {
images.forEach((img, i) => {
img.classList.toggle('active', i === index);
});
}
function showNextImage() {
currentIndex = (currentIndex + 1) % images.length;
showImage(currentIndex);
}
function showPrevImage() {
currentIndex = (currentIndex - 1 + images.length) % images.length;
showImage(currentIndex);
}
nextButton.addEventListener('click', showNextImage);
prevButton.addEventListener('click', showPrevImage);
// 自动播放功能(可选)
setInterval(showNextImage, 3000); // 每3秒切换一次图片
// 添加淡入淡出效果
images.forEach(img => {
img.addEventListener('transitionend', () => {
if (!img.classList.contains('active')) {
img.style.opacity = 0;
}
});
});
// 初始化时设置非活动图片的透明度
images.forEach((img, i) => {
if (i !== currentIndex) {
img.style.opacity = 0;
}
});
});

Tab切换功能
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tab Switch</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="tabs">
<button class="tab-button" data-tab="1">Tab 1</button>
<button class="tab-button" data-tab="2">Tab 2</button>
<button class="tab-button" data-tab="3">Tab 3</button>
</div>
<div class="tab-content">
<div class="tab-pane" id="tab-1">Content for Tab 1</div>
<div class="tab-pane" id="tab-2">Content for Tab 2</div>
<div class="tab-pane" id="tab-3">Content for Tab 3</div>
</div>
<script src="script.js"></script>
</body>
</html>

css
/* styles.css */
body {
font-family: Arial, sans-serif;
}
.tabs {
display: flex;
margin-bottom: 20px;
}
.tab-button {
padding: 10px 20px;
margin-right: 5px;
background-color: #f0f0f0;
border: 1px solid #ccc;
cursor: pointer;
}
.tab-button:hover {
background-color: #e0e0e0;
}
.tab-pane {
display: none;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
}
.tab-pane.active {
display: block;
}

js
// script.js
document.addEventListener('DOMContentLoaded', function() {
const tabButtons = document.querySelectorAll('.tab-button');
const tabPanes = document.querySelectorAll('.tab-pane');
tabButtons.forEach(button => {
button.addEventListener('click', function() {
tabButtons.forEach(b => b.classList.remove('active'));
tabPanes.forEach(p => p.classList.remove('active'));
const tabId = this.getAttribute('data-tab');
this.classList.add('active');
document.getElementById(`tab-${tabId}`).classList.add('active');
});
});
if (tabButtons.length > 0) {
tabButtons[0].click();
}
});

模态框 (Modal)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模态框示例</title>
<style>
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
.modal-content {
position: relative;
margin: 10% auto;
padding: 20px;
width: 80%;
max-width: 500px;
background-color: white;
border-radius: 5px;
}
.close {
position: absolute;
top: 10px;
right: 15px;
font-size: 24px;
cursor: pointer;
}
.open-modal {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<button class="open-modal">打开模态框</button>
<div id="modal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<h2>模态框标题</h2>
<p>这是一个模态框内容。</p>
</div>
</div>
<script>
const modal = document.getElementById('modal');
const openBtn = document.querySelector('.open-modal');
const closeBtn = document.querySelector('.close');
openBtn.onclick = () => {
modal.style.display = 'block';
};
closeBtn.onclick = () => {
modal.style.display = 'none';
};
window.onclick = (e) => {
if (e.target === modal) {
modal.style.display = 'none';
}
};
</script>
</body>
</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>
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: white;
min-width: 160px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content.show {
display: block;
}
.dropdown-btn {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="dropdown">
<button class="dropdown-btn">下拉菜单</button>
<div class="dropdown-content">
<a href="#">链接 1</a>
<a href="#">链接 2</a>
<a href="#">链接 3</a>
</div>
</div>
<script>
const dropdown = document.querySelector('.dropdown');
const dropdownContent = document.querySelector('.dropdown-content');
dropdown.addEventListener('mouseover', () => {
dropdownContent.classList.add('show');
});
dropdown.addEventListener('mouseout', () => {
dropdownContent.classList.remove('show');
});
</script>
</body>
</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>
.accordion {
margin: 20px 0;
}
.accordion-header {
padding: 10px;
background-color: #f1f1f1;
cursor: pointer;
display: flex;
justify-content: space-between;
}
.accordion-content {
padding: 0;
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.accordion-content.active {
padding: 10px;
max-height: 200px;
}
.arrow {
transition: transform 0.3s ease;
}
.arrow.rotate {
transform: rotate(180deg);
}
</style>
</head>
<body>
<div class="accordion">
<div class="accordion-header">
<span>标题 1</span>
<span class="arrow">▼</span>
</div>
<div class="accordion-content">
<p>这是手风琴内容 1。</p>
</div>
</div>
<div class="accordion">
<div class="accordion-header">
<span>标题 2</span>
<span class="arrow">▼</span>
</div>
<div class="accordion-content">
<p>这是手风琴内容 2。</p>
</div>
</div>
<script>
document.querySelectorAll('.accordion-header').forEach(header => {
header.addEventListener('click', () => {
const content = header.nextElementSibling;
content.classList.toggle('active');
header.querySelector('.arrow').classList.toggle('rotate');
});
});
</script>
</body>
</html>

自定义右键菜单
自定义右键菜单需要阻止默认的右键菜单,显示自定义的菜单,并根据点击位置定位。同时,点击页面其他位置时要隐藏菜单。这里可能需要动态创建菜单元素,并处理事件冒泡。
<div id="customMenu" style="display:none; position:absolute; background:#fff; box-shadow:0 0 5px #999">
<div class="menu-item">复制</div>
<div class="menu-item">粘贴</div>
<div class="menu-item">刷新</div>
</div>
<script>
document.addEventListener('contextmenu', (e) => {
e.preventDefault();
const menu = document.getElementById('customMenu');
menu.style.display = 'block';
menu.style.left = e.pageX + 'px';
menu.style.top = e.pageY + 'px';
});
document.addEventListener('click', () => {
document.getElementById('customMenu').style.display = 'none';
});
</script>

二、表单处理类
表单验证增强
<form id="myForm">
<input type="email" id="email" placeholder="邮箱">
<div class="error" id="emailError"></div>
<input type="password" id="password" placeholder="密码(6-12位)">
<div class="error" id="pwdError"></div>
<button type="submit">提交</button>
</form>
<script>
const form = document.getElementById('myForm');
// 实时验证
document.getElementById('email').addEventListener('input', (e) => {
const email = e.target.value;
const regex = /^[^\s@]+@[^\s@]+.[^\s@]+$/;
document.getElementById('emailError').textContent =
regex.test(email) ? '' : '邮箱格式不正确';
});
// 提交验证
form.addEventListener('submit', (e) => {
e.preventDefault();
const pwd = document.getElementById('password').value;
if(pwd.length < 6 || pwd.length > 12) {
document.getElementById('pwdError').textContent = '密码长度需6-12位';
return;
}
// 验证通过后提交
form.submit();
});
</script>

密码强度检测(输入安全相关)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>密码强度检测示例</title>
<style>
#password {
width: 100%;
padding: 10px;
margin-bottom: 20px;
}
#strengthMeter {
width: 100%;
height: 10px;
background-color: #ddd;
border-radius: 5px;
margin-bottom: 10px;
}
#strengthMeterFill {
height: 100%;
width: 0;
border-radius: 5px;
transition: width 0.3s, background-color 0.3s;
}
#strengthText {
font-size: 14px;
color: #666;
}
</style>
</head>
<body>
<input type="password" id="password" placeholder="输入密码">
<div id="strengthMeter">
<div id="strengthMeterFill"></div>
</div>
<div id="strengthText"></div>
<script>
document.getElementById('password').addEventListener('input', (e) => {
const password = e.target.value;
const meterFill = document.getElementById('strengthMeterFill');
const strengthText = document.getElementById('strengthText');
const strength = calculateStrength(password);
meterFill.style.width = strength + '%';
meterFill.style.backgroundColor = getStrengthColor(strength);
strengthText.textContent = getStrengthText(strength);
});
function calculateStrength(password) {
let strength = 0;
if (password.length >= 8) strength += 25;
if (/[A-Z]/.test(password)) strength += 25;
if (/[a-z]/.test(password)) strength += 25;
if (/[0-9]/.test(password)) strength += 25;
return strength;
}
function getStrengthColor(strength) {
if (strength < 25) return '#ff0000';
if (strength < 50) return '#ffaa00';
if (strength < 75) return '#ffdd00';
return '#4CAF50';
}
function getStrengthText(strength) {
if (strength < 25) return '弱';
if (strength < 50) return '一般';
if (strength < 75) return '强';
return '非常强';
}
</script>
</body>
</html>

三、数据存储类
本地存储记忆功能(localStorage/cookie操作)
本地存储记忆功能。这需要利用localStorage来保存用户的数据,比如表单输入或主题设置。在页面加载时读取存储的数据,并在数据变化时更新存储。例如,记住用户的搜索历史或表单填写内容。
// 保存数据
const saveData = () => {
const data = {
username: document.getElementById('name').value,
theme: document.body.classList.contains('dark') ? 'dark' : 'light'
};
localStorage.setItem('userPrefs', JSON.stringify(data));
};
// 读取数据
window.addEventListener('load', () => {
const saved = JSON.parse(localStorage.getItem('userPrefs'));
if(saved) {
document.getElementById('name').value = saved.username;
if(saved.theme === 'dark') document.body.classList.add('dark');
}
});
// 输入时自动保存
document.getElementById('name').addEventListener('input', saveData);

四、动态内容处理
实时搜索过滤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实时搜索过滤示例</title>
<style>
#searchInput {
width: 100%;
padding: 10px;
margin-bottom: 20px;
}
.item {
padding: 10px;
margin-bottom: 5px;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<input type="text" id="searchInput" placeholder="搜索...">
<div class="item">项目 1</div>
<div class="item">项目 2</div>
<div class="item">项目 3</div>
<div class="item">项目 4</div>
<div class="item">项目 5</div>
<script>
document.getElementById('searchInput').addEventListener('input', (e) => {
const searchTerm = e.target.value.toLowerCase();
document.querySelectorAll('.item').forEach(item => {
const text = item.textContent.toLowerCase();
item.style.display = text.includes(searchTerm) ? 'block' : 'none';
});
});
</script>
</body>
</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>
#loadMore {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.item {
padding: 10px;
margin-bottom: 5px;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<div id="content">
<div class="item">项目 1</div>
<div class="item">项目 2</div>
<div class="item">项目 3</div>
</div>
<button id="loadMore">加载更多</button>
<script>
let currentPage = 1;
const loadMoreBtn = document.getElementById('loadMore');
loadMoreBtn.addEventListener('click', () => {
currentPage++;
// 模拟数据加载
setTimeout(() => {
const data = [`项目 ${currentPage * 3 - 2}`, `项目 ${currentPage * 3 - 1}`, `项目 ${currentPage * 3}`];
renderItems(data);
}, 1000);
});
function renderItems(data) {
const content = document.getElementById('content');
data.forEach(item => {
const div = document.createElement('div');
div.className = 'item';
div.textContent = item;
content.appendChild(div);
});
}
</script>
</body>
</html>

随机名言生成器
随机名言生成器需要预定义名言数组,随机选择一条显示,并可能通过按钮点击切换。如果用户需要,可以扩展为从API获取数据,但当前需求是纯JS,所以先使用本地数据。
<div id="quoteDisplay"></div>
<button onclick="newQuote()">新语录</button>
<script>
const quotes = [
"代码写得好,头发掉得少",
"Ctrl+C/V 是程序员最高礼仪",
"程序不工作?试试console.log()",
"永远相信:下一个版本会更好"
];
function newQuote() {
const randomIndex = Math.floor(Math.random() * quotes.length);
document.getElementById('quoteDisplay').textContent = quotes[randomIndex];
}
// 初始化
newQuote();
</script>

五、实用工具类
网页计时器/倒计时
网页计时器/倒计时需要用到setInterval来更新时间显示,处理开始、暂停和重置功能。需要注意时间的格式化,如补零显示,并在倒计时结束时触发事件。
<div id="timer">00:00:00</div>
<button onclick="startTimer()">开始</button>
<button onclick="pauseTimer()">暂停</button>
<script>
let seconds = 0;
let timerId;
function formatTime(sec) {
const h = Math.floor(sec/3600).toString().padStart(2,'0');
const m = Math.floor(sec%3600/60).toString().padStart(2,'0');
const s = (sec%60).toString().padStart(2,'0');
return `${h}:${m}:${s}`;
}
function startTimer() {
if(!timerId) {
timerId = setInterval(() => {
seconds++;
document.getElementById('timer').textContent = formatTime(seconds);
}, 1000);
}
}
function pauseTimer() {
clearInterval(timerId);
timerId = null;
}
</script>

复制到剪贴板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>复制到剪贴板示例</title>
<style>
#copyText {
width: 100%;
padding: 10px;
margin-bottom: 20px;
background-color: #f1f1f1;
}
#copyBtn {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="copyText">这是要复制的文本</div>
<button id="copyBtn">复制到剪贴板</button>
<script>
document.getElementById('copyBtn').addEventListener('click', () => {
const text = document.getElementById('copyText').innerText;
navigator.clipboard.writeText(text)
.then(() => {
alert('已复制!');
})
.catch(err => {
console.error('复制失败:', err);
// 降级方案
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
alert('已复制!');
});
});
</script>
</body>
</html>

简易画板功能(图形交互工具)
简易画板功能需要处理canvas的鼠标事件,跟踪鼠标位置来绘制路径。可能需要设置画笔属性,如颜色和粗细,并实现清除画布的功能。
<canvas id="myCanvas" width="500" height="300"></canvas>
<button onclick="clearCanvas()">清空</button>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
let isDrawing = false;
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
function startDrawing(e) {
isDrawing = true;
ctx.beginPath();
ctx.moveTo(e.offsetX, e.offsetY);
}
function draw(e) {
if(!isDrawing) return;
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
function stopDrawing() {
isDrawing = false;
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
</script>

六、用户体验优化
回到顶部按钮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>回到顶部按钮示例</title>
<style>
body {
height: 2000px;
}
#topBtn {
position: fixed;
bottom: 20px;
right: 20px;
display: none;
width: 50px;
height: 50px;
background-color: #4CAF50;
color: white;
border-radius: 50%;
text-align: center;
line-height: 50px;
cursor: pointer;
}
</style>
</head>
<body>
<div style="height: 1500px; background-color: #f1f1f1;"></div>
<button id="topBtn">↑</button>
<script>
window.onscroll = () => {
document.getElementById('topBtn').style.display =
(document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) ? 'block' : 'none';
};
document.getElementById('topBtn').onclick = () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
};
window.onload = () => {
document.getElementById('topBtn').style.display = 'none';
};
</script>
</body>
</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>
.lazyload {
width: 100%;
height: 200px;
background-color: #f1f1f1;
margin: 20px 0;
}
</style>
</head>
<body>
<img data-src="https://via.placeholder.com/800x200" class="lazyload" alt="Lazy-loaded image">
<img data-src="https://via.placeholder.com/800x200" class="lazyload" alt="Lazy-loaded image">
<img data-src="https://via.placeholder.com/800x200" class="lazyload" alt="Lazy-loaded image">
<div style="height: 1000px;"></div>
<script>
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('.lazyload').forEach(img => observer.observe(img));
</script>
</body>
</html>

原生js图片放大镜效果
图片放大镜效果比较复杂。需要监听鼠标移动事件,计算放大区域的位置和比例,使用canvas来绘制放大后的图像。可能需要处理图片的加载和缩放比例,确保放大镜跟随鼠标移动。
<div class="img-container">
<img src="small.jpg" id="targetImg">
<div id="magnifier" style="display:none; width:200px; height:200px; position:absolute"></div>
</div>
<script>
const img = document.getElementById('targetImg');
const magnifier = document.getElementById('magnifier');
img.addEventListener('mousemove', (e) => {
const rect = img.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
magnifier.style.display = 'block';
magnifier.style.background = `
url(${img.src})
no-repeat
${-x*2}px ${-y*2}px
`;
magnifier.style.left = e.pageX + 15 + 'px';
magnifier.style.top = e.pageY + 15 + 'px';
});
img.addEventListener('mouseleave', () => {
magnifier.style.display = 'none';
});
</script>

暗黑模式切换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>暗黑模式切换示例</title>
<style>
body {
transition: background-color 0.3s, color 0.3s;
}
body.dark-mode {
background-color: #333;
color: white;
}
#darkModeToggle {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<button id="darkModeToggle">切换暗黑模式</button>
<script>
const toggle = document.getElementById('darkModeToggle');
toggle.addEventListener('click', () => {
document.body.classList.toggle('dark-mode');
const theme = document.body.classList.contains('dark-mode') ? 'dark' : 'light';
localStorage.setItem('theme', theme);
});
window.onload = () => {
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
document.body.classList.add('dark-mode');
}
};
</script>
</body>
</html>

网页主题色切换
网页主题色切换可以通过切换CSS类或直接修改样式属性,使用localStorage记住用户选择的主题。需要考虑如何动态改变主题颜色,并在页面加载时应用已保存的主题。
<button onclick="toggleTheme()">切换主题</button>
<script>
function toggleTheme() {
const root = document.documentElement;
const isDark = root.classList.toggle('dark-theme');
// 保存主题状态
localStorage.setItem('theme', isDark ? 'dark' : 'light');
}
// 初始化主题
document.addEventListener('DOMContentLoaded', () => {
const savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.classList.toggle('dark-theme', savedTheme === 'dark');
});
/* CSS需配合:
:root { --bg: #fff; --text: #333; }
.dark-theme { --bg: #222; --text: #fff; }
body { background: var(--bg); color: var(--text); }
*/
</script>

七、视觉效果类
点击切换图片(基础视觉交互)
<!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;
}
.nav {
width: 80%;
margin: 0 auto;
height: 65px;
display: flex;
}
.nav span {
flex: 1;
height: 65px;
text-align: center;
line-height: 65px;
font-size: 24px;
font-weight: bold;
cursor: pointer; /* 添加鼠标指针样式 */
}
.nav .siz {
background: orange; /* 高亮显示的导航项背景色 */
}
.content {
width: 80%;
height: 500px;
margin: 20px auto; /* 调整内容与导航之间的间距 */
display: flex;
flex-wrap: wrap; /* 允许内容换行 */
}
.content div {
display: none; /* 默认隐藏所有内容区域 */
width: 49%; /* 设置每个内容区域的宽度 */
margin: 0.5%; /* 设置内容区域之间的间距 */
box-sizing: border-box; /* 包含内边距和边框在内计算元素的总宽度和高度 */
}
.content .show {
display: block; /* 显示当前高亮的内容区域 */
}
.content img {
width: 100%; /* 图片宽度自适应内容区域 */
height: auto; /* 图片高度自动调整以保持比例 */
}
</style>
</head>
<body>
<div class="nav"></div>
<div class="content"></div>
<script>
let car = {
data: [
{ name: '产品1', pics: ['img1-1.jpg', 'img1-2.jpg'] },
{ name: '产品2', pics: ['img2-1.jpg', 'img2-2.jpg'] },
// ... 可以继续添加更多产品数据
]
};
let data = car.data;
let nav = document.querySelector(".nav");
let content = document.querySelector(".content");
// 渲染导航和内容区域
for (let i = 0; i < data.length; i++) {
let span = document.createElement("span");
span.innerText = data[i].name;
span.onclick = function () {
// 移除所有span和div的siz和show类
let navSpans = document.querySelectorAll(".nav span");
let contentDivs = document.querySelectorAll(".content div");
navSpans.forEach(span => span.className = '');
contentDivs.forEach(div => div.className = '');
// 给当前点击的span和对应的div添加siz和show类
this.className = 'siz';
contentDivs[i].className = 'show';
}
nav.appendChild(span);
let div = document.createElement("div");
let img1 = document.createElement("img");
let img2 = document.createElement("img");
// 这里虽然创建了两个img元素,但实际上每个div只显示一个(根据需求调整)
// 为了简化示例,这里只设置第一个img的src,第二个可以隐藏或根据需求处理
img1.setAttribute("src", data[i].pics[0]);
// img2.setAttribute("src", data[i].pics[1]);
// 如果需要显示两张图片,可以取消注释并调整CSS布局
div.appendChild(img1);
// div.appendChild(img2);
// 如果需要显示两张图片,可以取消注释
content.appendChild(div);
}
// 设置初始状态:默认显示第一个产品/项目
let navSpans = document.querySelectorAll(".nav span");
let contentDivs = document.querySelectorAll(".content div");
if (navSpans.length > 0 && contentDivs.length > 0) {
navSpans[0].className = 'siz';
contentDivs[0].className = 'show';
}
</script>
</body>
</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>
.animate-on-scroll {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.5s, transform 0.5s;
}
.animate-on-scroll.active {
opacity: 1;
transform: translateY(0);
}
.box {
width: 100%;
height: 200px;
background-color: #f1f1f1;
margin: 20px 0;
padding: 20px;
box-sizing: border-box;
}
.spacer {
height: 1000px;
background-color: #f9f9f9;
}
</style>
</head>
<body>
<div class="spacer"></div>
<div class="animate-on-scroll box">动画内容 1</div>
<div class="animate-on-scroll box">动画内容 2</div>
<div class="animate-on-scroll box">动画内容 3</div>
<div class="spacer"></div>
<script>
window.addEventListener('scroll', () => {
document.querySelectorAll('.animate-on-scroll').forEach(el => {
const rect = el.getBoundingClientRect();
if (rect.top < window.innerHeight * 0.8) {
el.classList.add('active');
}
});
});
</script>
</body>
</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>
.parallax {
position: relative;
height: 500px;
background-image: url('https://via.placeholder.com/1920x1080');
background-size: cover;
background-position: center;
}
.content {
height: 1000px;
background-color: #f1f1f1;
padding: 20px;
}
</style>
</head>
<body>
<div class="parallax"></div>
<div class="content">
<p>滚动页面查看视差效果。</p>
<!-- 添加更多内容 -->
</div>
<script>
window.addEventListener('scroll', () => {
const scrolled = window.pageYOffset;
document.querySelector('.parallax').style.transform = `translateY(${scrolled * 0.5}px)`;
});
</script>
</body>
</html>

此文尚需更新,敬请期待
码字不易,各位大佬点点赞呗