50天50个前端项目 - HTML/CSS和JavaScript实战合集
项目概述
这是一个全面的前端项目集合,包含50个独立的Web开发项目,每个项目都专注于不同的前端技术和交互效果。从基础的DOM操作到复杂的动画实现,这个合集涵盖了现代前端开发的各个方面。
功能特性
- 丰富的动画效果:包含3D盒子背景、旋转导航、模糊加载等多种动画
- 实用的交互组件:进度步骤、自定义滑块、待办列表、笔记应用等
- 响应式设计:所有项目都适配不同屏幕尺寸
- 纯前端实现:仅使用HTML、CSS和JavaScript,无后端依赖
- 模块化结构:每个项目独立,便于学习和复用
- 现代API应用:包含Fetch API、Canvas绘图、本地存储等现代Web技术
安装指南
环境要求
- 现代Web浏览器(Chrome、Firefox、Safari、Edge等)
- 文本编辑器(VS Code、Sublime Text等)
- 本地服务器(可选,用于某些需要HTTP协议的功能)
使用步骤
- 克隆或下载项目到本地
- 进入任意项目文件夹
- 用浏览器打开HTML文件即可运行
- 或使用本地服务器:
# 使用Python python -m http.server 8000# 使用Node.js npx http-server
使用说明
基础项目示例
扩展卡片(Expanding Cards)
点击不同的卡片实现展开和收缩效果:
<div class="container"><div class="panel active" style="background-image: url('image1.jpg')"><h3>标题1</h3></div><div class="panel" style="background-image: url('image2.jpg')"><h3>标题2</h3></div>
</div>
const panels = document.querySelectorAll('.panel')panels.forEach(panel => {panel.addEventListener('click', () => {removeActiveClasses()panel.classList.add('active')})
})function removeActiveClasses() {panels.forEach(panel => {panel.classList.remove('active')})
}
进度步骤(Progress Steps)
实现多步骤表单的进度指示:
const progress = document.getElementById('progress')
const prev = document.getElementById('prev')
const next = document.getElementById('next')
const circles = document.querySelectorAll('.circle')let currentActive = 1next.addEventListener('click', () => {currentActive++if(currentActive > circles.length) {currentActive = circles.length}update()
})function update() {circles.forEach((circle, idx) => {if(idx < currentActive) {circle.classList.add('active')} else {circle.classList.remove('active')}})const actives = document.querySelectorAll('.active')progress.style.width = (actives.length - 1) / (circles.length - 1) * 100 + '%'
}
API集成项目
GitHub个人资料搜索
集成GitHub API实现用户搜索:
const APIURL = 'https://api.github.com/users/'async function getUser(username) {try {const { data } = await axios(APIURL + username)createUserCard(data)getRepos(username)} catch(err) {if(err.response.status == 404) {createErrorCard('未找到该用户名')}}
}function createUserCard(user) {const userID = user.name || user.loginconst userBio = user.bio ? `<p>${user.bio}</p>` : ''const cardHTML = `<div class="card"><div><img src="${user.avatar_url}" alt="${user.name}" class="avatar"></div><div class="user-info"><h2>${userID}</h2>${userBio}<ul><li>${user.followers} <strong>关注者</strong></li><li>${user.following} <strong>关注中</strong></li><li>${user.public_repos} <strong>仓库</strong></li></ul><div id="repos"></div></div></div>`main.innerHTML = cardHTML
}
核心代码详解
1. 动画倒计时实现
const nums = document.querySelectorAll('.nums span')
const counter = document.querySelector('.counter')
const finalMessage = document.querySelector('.final')function runAnimation() {nums.forEach((num, idx) => {const nextToLast = nums.length - 1num.addEventListener('animationend', (e) => {// 处理进入动画结束if(e.animationName === 'goIn' && idx !== nextToLast) {num.classList.remove('in')num.classList.add('out')} // 处理离开动画结束else if(e.animationName === 'goOut' && num.nextElementSibling) {num.nextElementSibling.classList.add('in')} // 所有动画完成else {counter.classList.add('hide')finalMessage.classList.add('show')}})})
}
2. 自定义范围滑块
const range = document.getElementById('range')range.addEventListener('input', (e) => {const value = +e.target.valueconst label = e.target.nextElementSibling// 获取元素宽度进行计算const range_width = getComputedStyle(e.target).getPropertyValue('width')const label_width = getComputedStyle(label).getPropertyValue('width')const num_width = +range_width.substring(0, range_width.length - 2)const num_label_width = +label_width.substring(0, label_width.length - 2)const max = +e.target.maxconst min = +e.target.min// 计算标签位置const left = value * (num_width / max) - num_label_width / 2 + scale(value, min, max, 10, -10)label.style.left = `${left}px`label.innerHTML = value
})// 数值映射函数
const scale = (num, in_min, in_max, out_min, out_max) => {return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
}
3. 本地存储笔记应用
const notes = JSON.parse(localStorage.getItem('notes'))// 初始化已有笔记
if(notes) {notes.forEach(note => addNewNote(note))
}function addNewNote(text = '') {const note = document.createElement('div')note.classList.add('note')note.innerHTML = `<div class="tools"><button class="edit"><i class="fas fa-edit"></i></button><button class="delete"><i class="fas fa-trash-alt"></i></button></div><div class="main ${text ? "" : "hidden"}"></div><textarea class="${text ? "hidden" : ""}"></textarea>`// 编辑功能const editBtn = note.querySelector('.edit')editBtn.addEventListener('click', () => {main.classList.toggle('hidden')textArea.classList.toggle('hidden')})// 自动保存到本地存储textArea.addEventListener('input', (e) => {const { value } = e.targetmain.innerHTML = marked(value)updateLS()})
}function updateLS() {const notesText = document.querySelectorAll('textarea')const notes = []notesText.forEach(note => notes.push(note.value))localStorage.setItem('notes', JSON.stringify(notes))
}
4. 电影搜索应用
const API_URL = 'https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=YOUR_API_KEY&page=1'
const IMG_PATH = 'https://image.tmdb.org/t/p/w1280'async function getMovies(url) {const res = await fetch(url)const data = await res.json()showMovies(data.results)
}function showMovies(movies) {main.innerHTML = ''movies.forEach((movie) => {const { title, poster_path, vote_average, overview } = movieconst movieEl = document.createElement('div')movieEl.classList.add('movie')movieEl.innerHTML = `<img src="${IMG_PATH + poster_path}" alt="${title}"><div class="movie-info"><h3>${title}</h3><span class="${getClassByRate(vote_average)}">${vote_average}</span></div><div class="overview"><h3>剧情简介</h3>${overview}</div>`main.appendChild(movieEl)})
}// 根据评分设置颜色
function getClassByRate(vote) {if(vote >= 8) return 'green'else if(vote >= 5) return 'orange'else return 'red'
}
这些项目展示了现代前端开发的核心技术,包括DOM操作、事件处理、API集成、动画实现和本地存储等,为前端开发者提供了宝贵的学习资源和实践参考。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码
公众号二维码