前言
主打:快速获取完善开发思想。
您是否在众多文章中看到过「50projects50days」项目的详细描述?垂涎三尺了?没有时间?如果您时间有限,或者只想快速领略其中的亮点,那么您来对地方了。
50projects50days项目地址:🌟🌟🌟🌟🌟
GitHub - bradtraversy/50projects50days: 50+ mini web projects using HTML, CSS & JS
简介: 想要快速领略「50projects50days」的精华,却又没有足够的时间?本文为您呈现这个项目系列的精华概览,每个项目都展示了不同的技术和创意,我们将深入剖析每个项目的关键代码和实现步骤,了解其背后的设计思想和技术原理。无论您是初学者还是有一定经验的开发者,本文都将为您提供灵感和知识,帮助您更好地理解和应用 HTML、CSS 和 JavaScript。无需大量时间投入,让我们一起探索这些项目,汲取前端技术的精华。前方的创意和知识等待着您的发现!
目录
由于篇幅问题,本文将分成数个部分来介绍项目系列。以下✅是已发布部分的导航
上期解析 26day-30day,项目展示。
- ✅ Double Vertical Slider(双垂直滑块)
- ✅ Toast Notification(Toast 通知)
- ✅ Github Profiles(请求git文件)
- ✅ Double Click Heart(双击出现♥♥)
- ✅ Auto Text Effect(自动文本出现效果)
本期解析 31day-35day,项目展示。
- ✅ [Password Generator(密码生成器)](#Password Generator(密码生成器) "#heading-3")
- ✅ [Good Cheap Fast(switch的生成)](#Good Cheap Fast(switch的生成) "#heading-6")
- ✅ [Notes App(记笔记小程序)](#Notes App(记笔记小程序) "#heading-9")
- ✅ [Animated Countdown(动画倒计时)](#Animated Countdown(动画倒计时) "#heading-12")
- ✅ [Image Carousel(图像旋转木马-左右滑动)](#Image Carousel(图像旋转木马-左右滑动) "#heading-15")
下期解析 36day-40day,项目展示。
传送门🚀
- ✅ 前端创意探索:速览「50projects50days」项目精华 - 第一部分(1-5 天)
- ✅ 前端创意探索:速览「50projects50days」项目精华 - 第二部分(6-10 天)
- ✅ 前端创意探索:速览「50projects50days」项目精华 - 第三部分(11-15 天)
- ✅ 前端创意探索:速览「50projects50days」项目精华 - 第四部分(16-20 天)
- ✅ 前端创意探索:速览「50projects50days」项目精华 - 第五部分(21-25 天)
- ✅ 前端创意探索:速览「50projects50days」项目精华 - 第六部分(26-30 天)
- ✅ 前端创意探索:速览「50projects50days」项目精华 - 第七部分(31-35 天)
- 前端创意探索:速览「50projects50days」项目精华 - 第八部分(36-40 天)
- 前端创意探索:速览「50projects50days」项目精华 - 第九部分(41-45 天)
- 前端创意探索:速览「50projects50days」项目精华 - 第十部分(46-50 天)
31、Password Generator(密码生成器)
主要关注点:复制文字。
实现效果:
这个密码生成器的实现效果是生成一个自定义长度和字符类型的密码,并且可以将生成的密码复制到剪贴板。
实现关键代码
HTML 结构:包括密码长度和字符类型的设置。
html
<div class="container">
<h2>Password Generator</h2>
<div class="result-container">
<span id="result"></span>
<button class="btn" id="clipboard">
<i class="far fa-clipboard"></i>
</button>
</div>
<div class="settings">
<div class="setting">
<label>Password Length</label>
<input type="number" id="length" min="4" max="20" value="20">
</div>
......
</div>
<button class="btn btn-large" id="generate">
Generate Password
</button>
</div>
JavaScript 逻辑:包括生成密码的算法和复制密码到剪贴板的功能。
copy文字
js
const clipboardEl = document.getElementById('clipboard');
clipboardEl.addEventListener('click', () => {
const password = resultEl.innerText;
if (!password) {
return;
}
navigator.clipboard.writeText(password);
alert('Password copied to clipboard!')
})
随机的密码
读取 check 得状态进行使用,需要一个一个判断,再去把random得数据拼起来
js
// 对每一个需要的字符排好顺序
const randomFunc = {
lower: getRandomLower, //一些随机内容的方法采用ASCⅡ来获取的String.fromCharCode(数字)
upper: getRandomUpper,
number: getRandomNumber,
symbol: getRandomSymbol
}
// 统一获取状态
generateEl.addEventListener('click', () => {
const length = +lengthEl.value
const hasLower = lowercaseEl.checked
const hasUpper = uppercaseEl.checked
const hasNumber = numbersEl.checked
const hasSymbol = symbolsEl.checked
// 统一去请求数据
resultEl.innerText = generatePassword(hasLower, hasUpper, hasNumber, hasSymbol, length)
})
// 数据的使用
function generatePassword (lower, upper, number, symbol, length) {
let generatedPassword = ''
const typesCount = lower + upper + number + symbol
//过滤掉不是true check的数据
const typesArr = [{ lower }, { upper }, { number }, { symbol }].filter(item => {
return Object.values(item)[0] //返回是true得
})
console.log(typesArr);
if (typesCount === 0) {
return ''
}
//开始循环得结果,length总长度,一次会foreach多少个typesCount
for (let i = 0; i < length; i += typesCount) {
typesArr.forEach(type => {
const funcName = Object.keys(type)[0] //在找到是谁得keys来对这个keys进行处理
generatedPassword += randomFunc[funcName]()
})
}
const finalPassword = generatedPassword.slice(0, length)
return finalPassword
}
function getRandomLower() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 97)
}
function getRandomUpper() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 65)
}
function getRandomNumber() {
return String.fromCharCode(Math.floor(Math.random() * 10) + 48)
}
function getRandomSymbol() {
const symbols = '!@#$%^&*(){}[]=<>/,.'
return symbols[Math.floor(Math.random() * symbols.length)]
}
实现步骤:
- 设计一手,用户可以设置密码的长度以及包含的字符类型的界面。
- 点击 "Generate Password" 按钮将生成密码并显示在页面上,利用函数与传入的字符长度,来确定随机的内容。
- 点击调用方法
navigator.clipboard.writeText("内容")
,剪贴板图标可以将密码复制到剪贴板。
CSS样式
🐯CSS样式用于美化页面和界面元素的样式,使其看起来更吸引人
有点意思的是字体图标的引入 <i class="far fa-clipboard"></i>
css
@import url('https://fonts.googleapis.com/css?family=Muli&display=swap');
总结:
这个密码生成器实现了一个简单而实用的功能,用户可以轻松地生成自定义密码并将其复制到剪贴板。但是,这个复制仅仅适用于web,如果是 H5
与 webview
的环境,注意复制文字的兼容性问题。
32、Good Cheap Fast(switch的生成)
主要关注点:如何画出switch,关注一下CSS的效果。
实现效果:
这个页面实现了一个选择性的切换开关,用户可以选择其中两项,但无法同时选择全部三项。
实现关键代码
HTML 结构:开关按钮和标签。
html
<h2>How do you want your project to be?</h2>
<!-- 开关按钮的结构 -->
<div class="toggle-container">
<input type="checkbox" id="good" class="toggle">
<label for="good" class="label">
<div class="ball"></div>
</label>
<span>Good</span>
</div>
<!-- 类似的结构用于"cheap"和"fast"选项 -->
JavaScript 逻辑:用于控制开关的行为,确保用户无法同时选择全部三项。
js
const toggles = document.querySelectorAll('.toggle')
const good = document.querySelector('#good')
const cheap = document.querySelector('#cheap')
const fast = document.querySelector('#fast')
toggles.forEach(toggle => toggle.addEventListener('change', (e) => doTheTrick(e.target)))
// 三个全都true,进入判断,去掉一个显示为true的按钮
function doTheTrick(theClickedOne) {
if(good.checked && cheap.checked && fast.checked) {
if(good === theClickedOne) {
fast.checked = false
}
if(cheap === theClickedOne) {
good.checked = false
}
if(fast === theClickedOne) {
cheap.checked = false
}
}
}
实现步骤:
- 用户可以选择他们三项中的两项。
- 如果用户选择了其中两项,系统会自动取消未选择的那一项。
- 页面中的开关按钮会在用户点击后切换状态,并通过动画效果显示用户的选择。
CSS样式
🐯开关按钮的外观,包括按钮的颜色和动画效果。
css
.toggle-container {
display: flex;
align-items: center;
margin: 10px 0;
width: 200px;
}
.toggle {
visibility: hidden; //隐藏check为不可见
}
/*使用label利用for连接,画出switch页面 */
.label {
position: relative;
background-color: #d0d0d0;
border-radius: 50px;
cursor: pointer;
display: inline-block;
margin: 0 15px 0;
width: 80px;
height: 40px;
}
/* checked为选中状态 */
.toggle:checked + .label {
background-color: #8e44ad;
}
.ball {
background: #fff;
height: 34px;
width: 34px;
border-radius: 50%;
position: absolute;
top: 3px;
left: 3px;
align-items: center;
justify-content: center;
animation: slideOff 0.3s linear forwards;
}
.toggle:checked + .label .ball {
animation: slideOn 0.3s linear forwards;
}
/* 点击打开从0移动到40px */
@keyframes slideOn {
0% {
transform: translateX(0) scale(1);
}
50% {
transform: translateX(20px) scale(1.2);
}
100% {
transform: translateX(40px) scale(1);
}
}
@keyframes slideOff {
0% {
transform: translateX(40px) scale(1);
}
50% {
transform: translateX(20px) scale(1.2);
}
100% {
transform: translateX(0) scale(1);
}
}
总结:
这个页面实现了一个有趣的功能,用户可以选择项目的特性,但只能选择其中两项。开关按钮的动画效果使页面更加生动。
如果想深入了解看一下,这篇文章 如何简单实现switch开关组件
33、Notes App(记笔记小程序)
主要关注点:Notes App 页面的实现。
实现效果:
这个页面实现了一个简单的笔记应用,用户可以添加、编辑、删除笔记,同时也支持 Markdown
格式。
实现关键代码
HTML 结构:添加按钮和笔记显示区域。
html
<button class="add" id="add">
<i class="fas fa-plus"></i> Add note
</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/1.2.2/marked.min.js"></script>
JavaScript 逻辑:用于添加、编辑、删除笔记以及将笔记保存到本地存储。
添加新的Node
js
function addNewNote(text = '') {
const note = document.createElement('div')
note.classList.add('note')
// 对文本的控制,采用hidden的css样式
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')
const deleteBtn = note.querySelector('.delete')
const main = note.querySelector('.main')
const textArea = note.querySelector('textarea')
textArea.value = text
main.innerHTML = marked(text)
deleteBtn.addEventListener('click', () => {
note.remove()
updateLS()
})
// 再次点击编辑变成不可编辑状态,采用的是,display:none
editBtn.addEventListener('click', () => {
main.classList.toggle('hidden')
textArea.classList.toggle('hidden')
})
textArea.addEventListener('input', (e) => {
const { value } = e.target
main.innerHTML = marked(value)
updateLS()
})
document.body.appendChild(note)
}
有趣点:marked(text)
与 text
的区别是什么
js
textArea.value = text // 普通文本
main.innerHTML = marked(text) //带有<p>文本</p>的效果
通过一个函数添加那么多相同的节点,删除的则也是自己点击的节点。
实现步骤:
- 用户可以点击
Add note
按钮来添加新的笔记。 - 每个笔记都有编辑和删除按钮,用户可以编辑笔记内容。
- 笔记支持
Markdown
格式,实时预览。 - 笔记会被保存到本地存储,以便用户下次访问时仍可见。
CSS样式
🐯XXXXXXXX:定义了XXXXXXXX。
css
.hidden {
display: none;
}
在类 main
与 textarea
标签中,来回切换
总结:
这个笔记应用允许用户方便地管理笔记,支持 Markdown
格式,同时也提供了简洁的用户界面
34、Animated Countdown(动画倒计时)
主要关注点:Animated Countdown
页面的实现。
实现效果:
这个页面实现了一个动画倒计时效果,从3倒数到0,最后显示 "GO" 按钮,用户可以点击 "Replay" 按钮重新开始倒计时。
实现关键代码
HTML 结构:倒计时数字和按钮。
html
<div class="counter">
<div class="nums">
<span class="in">3</span>
<span>2</span>
<span>1</span>
<span>0</span>
</div>
<h4>Get Ready</h4>
</div>
<div class="final">
<h1>GO</h1>
<button id="replay">
<span>Replay</span>
</button>
</div>
JavaScript 逻辑:用于控制倒计时动画和"Replay"按钮的功能。
可谓说的是,难点重重。代码全贴了,解析在里面
js
const nums = document.querySelectorAll('.nums span')
const counter = document.querySelector('.counter')
const finalMessage = document.querySelector('.final')
const replay = document.querySelector('#replay')
runAnimation()
function resetDOM () {
counter.classList.remove('hide')
finalMessage.classList.remove('show')
nums.forEach((num) => {
num.classList.value = ''
})
nums[0].classList.add('in')
}
function runAnimation () {
nums.forEach((num, idx) => {
const nextToLast = nums.length - 1
num.addEventListener('animationend', (e) => {
if (e.animationName === 'goIn' && idx !== nextToLast) {
num.classList.remove('in') //goIn 结束,回调 animationend
num.classList.add('out') //goOut 开始
} else if (e.animationName === 'goOut' && num.nextElementSibling) {
// goOut结束,给兄弟加上goIn再次回调 animationend
// 被addEventListener监听到了goIn结束了,所以就开始上面的if了
num.nextElementSibling.classList.add('in')
} else {
counter.classList.add('hide')
finalMessage.classList.add('show')
}
})
})
}
replay.addEventListener('click', () => {
resetDOM()
runAnimation()
})
实现步骤:
- 页面加载时自动开始倒计时,从 3 倒数到 0 。
- 倒计时数字具有动画效果,依次显示和隐藏。
- 当倒计时完成后,显示 "GO" 和 "Replay" 按钮。
- 用户可以点击 "Replay" 按钮重新开始倒计时。
CSS样式
🐯倒计时数字的外观,包括动画效果和按钮样式。
数字的隐藏与展示
css
.counter {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.counter.hide {
transform: translate(-50%, -50%) scale(0);
animation: hide 0.2s ease-out;
}
@keyframes hide {
0% {
transform: translate(-50%, -50%) scale(1);
}
100% {
transform: translate(-50%, -50%) scale(0);
}
}
.final {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
text-align: center;
}
.final.show {
transform: translate(-50%, -50%) scale(1);
animation: show 0.2s ease-out;
}
@keyframes show {
0% {
transform: translate(-50%, -50%) scale(0);
}
30% {
transform: translate(-50%, -50%) scale(1.4);
}
100% {
transform: translate(-50%, -50%) scale(1);
}
}
数字的动态效果
css
.nums {
color: #3498db;
font-size: 50px;
position: relative;
overflow: hidden;
width: 250px;
height: 50px;
}
.nums span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(120deg);
transform-origin: bottom center;
}
.nums span.in {
transform: translate(-50%, -50%) rotate(0deg);
animation: goIn 0.5s ease-in-out;
}
.nums span.out {
animation: goOut 0.5s ease-in-out;
}
/* 从120°到 0° 变成居中 ,*/
@keyframes goIn {
0% {
transform: translate(-50%, -50%) rotate(120deg);
}
30% {
transform: translate(-50%, -50%) rotate(-20deg);
}
60% {
transform: translate(-50%, -50%) rotate(10deg);
}
100% {
transform: translate(-50%, -50%) rotate(0deg);
}
}
/* 从0°到 -120° 变成居中 ,*/
@keyframes goOut {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
60% {
transform: translate(-50%, -50%) rotate(20deg);
}
100% {
transform: translate(-50%, -50%) rotate(-120deg);
}
}
总结:
这个动画倒计时页面为用户提供了一种娱乐和互动的方式,用户可以点击 "Replay" 按钮重新体验倒计时。
35、Image Carousel(图像旋转木马-左右滑动)
主要关注点:图片的走马灯效果。
实现效果:
这个页面实现了一个图片轮播功能,用户可以点击 "Prev" 和 "Next" 按钮切换图片,也可以自动轮播图片。页面中有四张不同的图片,点击按钮或自动轮播时,图片会水平滚动切换。
实现关键代码
HTML 结构:图片容器和按钮。
html
<div class="carousel">
<div class="image-container" id="imgs">
<!-- 四张图片 -->
</div>
<div class="buttons-container">
<button id="left" class="btn">Prev</button>
<button id="right" class="btn">Next</button>
</div>
</div>
JavaScript 逻辑:用于控制图片轮播的切换和按钮功能。
js
const imgs = document.getElementById('imgs')
const leftBtn = document.getElementById('left')
const rightBtn = document.getElementById('right')
const img = document.querySelectorAll('#imgs img')
let idx = 0
// 滚动的计时器
let interval = setInterval(run, 2000)
function run() {
idx++
changeImage()
}
function resetInterval() {
clearInterval(interval) //被btn点击,清除上一次的,开启下一次的计时器运行
interval = setInterval(run, 2000)
}
function changeImage() {
// 滚动的效果
if(idx > img.length - 1) {
idx = 0
} else if(idx < 0) {
idx = img.length - 1
}
imgs.style.transform = `translateX(${-idx * 500}px)`
}
rightBtn.addEventListener('click', () => {
idx++
changeImage()
resetInterval()
})
leftBtn.addEventListener('click', () => {
idx--
changeImage()
resetInterval()
})
实现步骤:
- 页面加载时自动开始图片轮播,每2秒切换一张图片。
- 用户可以点击 "Prev" 和 "Next" 按钮手动切换图片,点击按钮后会重置自动轮播定时器。
- 图片循环轮播,切换到最后一张后回到第一张。
- 利用
transform
去实现移动,在css中采用transition: transform 0.5s ease-in-out
,优化动画效果。
CSS样式
🐯括图片大小、按钮样式和轮播效果。
css
.image-container {
display: flex;
transform: translateX(0);
transition: transform 0.5s ease-in-out;
}
img {
width: 500px;
height: 500px;
object-fit: cover;
}
总结:
这个图片轮播页面提供了交互性,用户可以点击按钮或自动轮播来浏览不同的图片。
😘预知后事如何,待下回分解