前端创意探索:速览「50projects50days」项目精华 - 第五部分(46-50 天)

前言

主打:快速获取完善开发思想。

您是否在众多文章中看到过「50projects50days」项目的详细描述?垂涎三尺了?没有时间?如果您时间有限,或者只想快速领略其中的亮点,那么您来对地方了。


50projects50days项目地址:🌟🌟🌟🌟🌟

GitHub - bradtraversy/50projects50days: 50+ mini web projects using HTML, CSS & JS


简介: 想要快速领略「50projects50days」的精华,却又没有足够的时间?本文为您呈现这个项目系列的精华概览,每个项目都展示了不同的技术和创意,我们将深入剖析每个项目的关键代码和实现步骤,了解其背后的设计思想和技术原理。无论您是初学者还是有一定经验的开发者,本文都将为您提供灵感和知识,帮助您更好地理解和应用 HTML、CSS 和 JavaScript。无需大量时间投入,让我们一起探索这些项目,汲取前端技术的精华。前方的创意和知识等待着您的发现!

目录

由于篇幅问题,本文将分成数个部分来介绍项目系列。以下✅是已发布部分的导航

上期解析 41day-45day,项目展示。

本期解析 46day-50day,项目展示。

  • ✅ [Quiz App(判题小程序)](#Quiz App(判题小程序) "#heading-3")
  • ✅ [Testimonial Box Switcher(自动盒子切换器)](#Testimonial Box Switcher(自动盒子切换器) "#heading-6")
  • ✅ [Random Image Feed(随机图像返回)](#Random Image Feed(随机图像返回) "#heading-9")
  • ✅ [Todo List(事项清单)](#Todo List(事项清单) "#heading-12")
  • ✅ [Insect Catch Game(昆虫捕捉游戏)](#Insect Catch Game(昆虫捕捉游戏) "#heading-15")

下期解析 无,项目展示。

没有了,真没有了。😘

传送门🚀

46、Quiz App(测验小程序)

主要关注点:关注一下数据的存储结构

实现效果:

简单的测验应用(Quiz App)的示例,用户可以回答一系列问题并获取最终得分。

实现关键代码

HTML 结构:问题、选项、提交按钮以及最终结果的显示

html 复制代码
<div class="quiz-container" id="quiz">
      <div class="quiz-header">
        <h2 id="question">Question text</h2>
        <ul>
          <li>
            <input type="radio" name="answer" id="a" class="answer">
            <label for="a" id="a_text">Question</label>
          </li>

          <li>
            <input type="radio" name="answer" id="b" class="answer">
            <label for="b" id="b_text">Question</label>
          </li>

          <li>
            <input type="radio" name="answer" id="c" class="answer">
            <label for="c" id="c_text">Question</label>
          </li>

          <li>
            <input type="radio" name="answer" id="d" class="answer">
            <label for="d" id="d_text">Question</label>
          </li>
        </ul>
      </div>
      <button id="submit">Submit</button>
    </div>

JavaScript 逻辑:包括测验的数据、事件监听器和得分计算逻辑

答题的问题形成一种数组结构。

js 复制代码
const quizData = [
    {
        question: "Which language runs in a web browser?",
        a: "Java",
        b: "C",
        c: "Python",
        d: "JavaScript",
        correct: "d",
    },
    {
        question: "What does CSS stand for?",
        a: "Central Style Sheets",
        b: "Cascading Style Sheets",
        c: "Cascading Simple Sheets",
        d: "Cars SUVs Sailboats",
        correct: "b",
    },
    {
        question: "What does HTML stand for?",
        a: "Hypertext Markup Language",
        b: "Hypertext Markdown Language",
        c: "Hyperloop Machine Language",
        d: "Helicopters Terminals Motorboats Lamborginis",
        correct: "a",
    },
    {
        question: "What year was JavaScript launched?",
        a: "1996",
        b: "1995",
        c: "1994",
        d: "none of the above",
        correct: "b",
    },
];

问题的展现与判题

js 复制代码
    if(answer) { // 判断是否选择了答案
        if(answer === quizData[currentQuiz].correct) {
            score++  // 这一题正确就加
        }

        currentQuiz++ // 指针指到下一题

        if(currentQuiz < quizData.length) {
            loadQuiz() // 题数不对,那就下一条
        } else {
            //完成题数的处理
        }
    }

完整的JS

js 复制代码
const quiz = document.getElementById('quiz')
const answerEls = document.querySelectorAll('.answer')
const questionEl = document.getElementById('question')
const a_text = document.getElementById('a_text')
const b_text = document.getElementById('b_text')
const c_text = document.getElementById('c_text')
const d_text = document.getElementById('d_text')
const submitBtn = document.getElementById('submit')

let currentQuiz = 0
let score = 0

loadQuiz()

function loadQuiz() {
    deselectAnswers()

    const currentQuizData = quizData[currentQuiz]
    // 加载问题
    questionEl.innerText = currentQuizData.question
    a_text.innerText = currentQuizData.a
    b_text.innerText = currentQuizData.b
    c_text.innerText = currentQuizData.c
    d_text.innerText = currentQuizData.d
}

function deselectAnswers() {
    answerEls.forEach(answerEl => answerEl.checked = false)
}

function getSelected() {
    let answer
    
    answerEls.forEach(answerEl => {
        if (answerEl.checked) {
            answer = answerEl.id
        }
    })

    return answer
}

submitBtn.addEventListener('click', () => {
    const answer = getSelected()
    
    if (answer) {
        if (answer === quizData[currentQuiz].correct) {
            score++
        }

        currentQuiz++

        if (currentQuiz < quizData.length) {
            loadQuiz()
        } else {
            quiz.innerHTML = `
                <h2>You answered ${score}/${quizData.length} questions correctly</h2>

                <button onclick="location.reload()">Reload</button>
            `
        }
    }
})

实现步骤:

  1. 提供测验问题和答案数据。
  2. 监听提交按钮的点击事件,处理问题正确性,计算用户得分,显示最终结果。

CSS样式

🐯页面的外观和布局,包括问题、选项、按钮等的样式。

没有啥留意的,看一下按钮的变化把。

css 复制代码
button {
  background-color: #8e44ad;
  color: #fff;
  border: none;
  display: block;
  width: 100%;
  cursor: pointer;
  font-size: 1.1rem;
  font-family: inherit;
  padding: 1.3rem;
}

button:hover {
  background-color: #732d91;
}

button:focus {
  outline: none;
  background-color: #5e3370;
}

总结:

项目中用户回答一系列问题并获取最终得分,在答题中,把答题的问题形成一种数组结构,在点击下一题的同时,将 ++curryQuizIndex 移动角标,然后判断问题的长度是否到了最后一个(完成的效果),并且判断用户是否在这一题选择的正确(记分)。

47、Testimonial Box Switcher(自动的消息切换技术)

主要关注点:进度条的实现方式

实现效果:

简单的推荐信展示框(Testimonial Box)的示例,用于展示用户的推荐和评价

实现关键代码

HTML 结构:推荐信内容、用户信息和进度条

html 复制代码
<div class="testimonial-container">
      <div class="progress-bar"></div>
      <div class="fas fa-quote-right fa-quote"></div>
      <div class="fas fa-quote-left fa-quote"></div>
      <p class="testimonial">
       <!-- 内容-->
      </p>
      <div class="user">
        <img
          src="https://randomuser.me/api/portraits/women/46.jpg"
          alt="user"
          class="user-image"
        />
        <div class="user-details">
          <h4 class="username">Miyah Myles</h4>
          <p class="role">Marketing</p>
        </div>
      </div>
    </div>

JavaScript 逻辑:用于循环显示不同的推荐信内容

js 复制代码
// JavaScript 代码
const testimonialsContainer = document.querySelector('.testimonials-container')
const testimonial = document.querySelector('.testimonial')
const userImage = document.querySelector('.user-image')
const username = document.querySelector('.username')
const role = document.querySelector('.role')

const testimonials = [
  {
    name: 'Miyah Myles',
    position: 'Marketing',
    photo: 'URL_TO_PHOTO',
    text: '推荐信文本内容1',
  },
  {
    name: 'June Cha',
    position: 'Software Engineer',
    photo: 'URL_TO_PHOTO',
    text: '推荐信文本内容2',
  },
  // (其他推荐信数据)
]

let idx = 1

function updateTestimonial() {
  const { name, position, photo, text } = testimonials[idx]

  testimonial.innerHTML = text
  userImage.src = photo
  username.innerHTML = name
  role.innerHTML = position

  idx++

  if (idx > testimonials.length - 1) {
    idx = 0
  }
}

setInterval(updateTestimonial, 10000)

实现步骤:

  1. 提供多个不同的推荐信数据。
  2. 使用定时器 setInterval 循环显示不同的推荐信内容。

CSS样式

🐯主要用于页面的外观和布局,包括推荐信内容、用户信息和进度条的样式。

主要关心进度条

css 复制代码
.progress-bar {
  background-color: #fff;
  height: 4px;
  width: 100%;
  animation: grow 10s linear infinite;
  transform-origin: left;
}

@keyframes grow {
  0% {
    transform: scaleX(0);
  }
  /*以下可不写*/
  100% {
    transform: scaleX(1);
  }
}

总结:

项目允许循环显示不同用户的推荐信,使用 setInterval 每隔10s时间自动切换下一个推荐信。

48、Random Image Feed(随机图像返回)

主要关注点:CSS中flex对布局的使用

实现效果:

生成随机图片的示例,图片来自 Unsplash,使用展示的弹性。

实现关键代码

HTML 结构:标题和用于显示图片的容器

html 复制代码
<h1 class="title">Random Image Feed</h1>
<div class="container"></div>

JavaScript 逻辑:动态加载随机图片,并将它们显示在容器中

js 复制代码
const container = document.querySelector('.container')
const unsplashURL = 'https://source.unsplash.com/random/'
const rows = 5 // 加载五行

// 一行3列
for(let i = 0; i < rows * 3; i++) {
    const img = document.createElement('img')
    img.src = `${unsplashURL}${getRandomSize()}`
    container.appendChild(img)
}

// 随机图片大小
function getRandomSize() {
    return `${getRandomNr()}x${getRandomNr()}`
}

function getRandomNr() {
    return Math.floor(Math.random() * 10) + 300
}

实现步骤:

  1. 使用 Unsplash 的随机图片 API 加载随机图片。
  2. 动态生成图片元素并将它们添加到容器中。

CSS样式

🐯页面的外观和布局。

css 复制代码
.container {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  max-width: 1000px; // 容器宽1000px
}

.container img {
  object-fit: cover;
  margin: 10px;
  height: 300px;
  width: 300px; // 一个width定死300 刚刚好可以排3个
  max-width: 100%;
}

总结:

生成了一个包含随机图片的图像流,使用flex弹性布局。

49、Todo List(事项清单)

主要关注点:监听鼠标左键都知道,下面有监听右键的,还有本地存储的一次格式转化

实现效果:

简单的待办事项列表示例,您可以添加、标记完成和删除待办事项

实现关键代码

HTML 结构:标题、输入表单和待办事项列表

html 复制代码
<h1>todos</h1>
<form id="form">
  <input type="text" class="input" id="input" placeholder="Enter your todo" autocomplete="off">
  <ul class="todos" id="todos"></ul>
</form>

<small>Left click to toggle completed. <br> Right click to delete todo</small>

JavaScript 逻辑:处理待办事项的添加、标记完成和删除操作,并将数据存储在本地存储中以便保留状态

点击监听

js 复制代码
todoEl.addEventListener('click', () => {
    //左键事件
})   
todoEl.addEventListener('contextmenu', (e) => {
    // 右键事件
}) 

完整js

js 复制代码
const form = document.getElementById('form')
const input = document.getElementById('input')
const todosUL = document.getElementById('todos')

const todos = JSON.parse(localStorage.getItem('todos'))

// 如果有数据,就渲染更新一下数据
if(todos) {
    todos.forEach(todo => addTodo(todo))
}

// 提交就新增数据
form.addEventListener('submit', (e) => {
    e.preventDefault()

    addTodo()
})

// 添加数据
function addTodo(todo) {
    let todoText = input.value

    if(todo) {
        todoText = todo.text
    }

    if(todoText) {
        const todoEl = document.createElement('li')
        if(todo && todo.completed) {
            todoEl.classList.add('completed')
        }

        todoEl.innerText = todoText

        todoEl.addEventListener('click', () => {
            todoEl.classList.toggle('completed')
            updateLS()
        }) 

        todoEl.addEventListener('contextmenu', (e) => {
            e.preventDefault()

            todoEl.remove()
            updateLS()
        }) 

        todosUL.appendChild(todoEl)

        input.value = ''

        updateLS()
    }
}

function updateLS() {
    todosEl = document.querySelectorAll('li')

    const todos = []

    todosEl.forEach(todoEl => {
        todos.push({
            text: todoEl.innerText,
            completed: todoEl.classList.contains('completed')
        })
    })
    // 数据存储本地
    localStorage.setItem('todos', JSON.stringify(todos))
}

实现步骤:

  1. 初始化待办事项列表,从本地存储 JSON.parse(localStorage.getItem('todos')) 中加载已保存的待办事项。
  2. 处理表单提交事件,添加新的待办事项。
  3. 处理点击事件以标记待办事项为已完成。
  4. 处理右键点击事件以删除待办事项。
  5. 更新 localStorage.setItem('todos', JSON.stringify(todos)) 本地存储中的待办事项数据。

CSS样式

🐯包括标题、输入表单、待办事项列表和小提示的样式

优先关心input框的变化

css 复制代码
form {
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
  max-width: 100%;
  width: 400px;
}

.input {
  border: none;
  color: #444;
  font-size: 2rem;
  padding: 1rem 2rem;
  display: block;
  width: 100%;
}

.input::placeholder {
  color: #d5d5d5;
}

.input:focus {
  outline-color: rgb(179, 131, 226);
}

总结:

示例允许您创建、管理和删除待办事项,我们主要关心右键事件 contextmenu与本地存储格式的转化:存 localStorage.setItem('todos', JSON.stringify(todos)) 、取JSON.parse(localStorage.getItem('todos'))

50、Insect Catch Game(昆虫捕捉游戏)

主要关注点:这个游戏怎么实现的

实现效果:

这是一个小游戏,您需要捕捉屏幕上出现的昆虫。

实现关键代码

HTML 结构:三个屏幕:起始屏幕、选择昆虫屏幕和游戏屏幕

起始屏幕包括游戏的标题和"Play Game"按钮。

html 复制代码
<div class="screen">
  <h1>Catch The Insect</h1>
  <button class="btn" id="start-btn">Play Game</button>
</div>

选择昆虫屏幕询问您的"favorite"昆虫,提供了不同昆虫的选项。

html 复制代码
<div class="screen">
      <h1>What is your "favorite" insect?</h1>
      <ul class="insects-list">
        <li>
          <button class="choose-insect-btn">
            <p>Fly</p>
            <img src="http://pngimg.com/uploads/fly/fly_PNG3946.png" alt="fly">
          </button>
        </li>
        <li>
          <button class="choose-insect-btn">
            <p>Mosquito</p>
            <img
               src="http://pngimg.com/uploads/mosquito/mosquito_PNG18175.png"
               alt="mosquito"
               />
          </button>
        </li>
        <li>
          <button class="choose-insect-btn">
            <p>Spider</p>
            <img
               src="http://pngimg.com/uploads/spider/spider_PNG12.png"
               alt="spider"
               />
          </button>
        </li>
        <li>
          <button class="choose-insect-btn">
            <p>Roach</p>
            <img
               src="http://pngimg.com/uploads/roach/roach_PNG12163.png"
               alt="roach"
               />
          </button>
        </li>
      </ul>
    </div>

游戏屏幕包括计时器、分数和一群飞行的昆虫。

html 复制代码
<div class="screen game-container" id="game-container">
    <h3 id="time" class="time">Time: 00:00</h3>
    <h3 id="score" class="score">Score: 0</h3>
    <h5 id="message" class="message">
    Are you annoyed yet? <br>
    You are playing an impossible game!!
    </h5>
</div>

JavaScript 逻辑:用于控制游戏的各个部分

js 复制代码
const screens = document.querySelectorAll('.screen');
const choose_insect_btns = document.querySelectorAll('.choose-insect-btn');
const start_btn = document.getElementById('start-btn')
const game_container = document.getElementById('game-container')
const timeEl = document.getElementById('time')
const scoreEl = document.getElementById('score')
const message = document.getElementById('message')
let seconds = 0
let score = 0
let selected_insect = {}

start_btn.addEventListener('click', () => screens[0].classList.add('up'))

// 选择一种昆虫
choose_insect_btns.forEach(btn => {
    btn.addEventListener('click', () => {
        const img = btn.querySelector('img')
        const src = img.getAttribute('src')
        const alt = img.getAttribute('alt')
        selected_insect = { src, alt }
        screens[1].classList.add('up')
        setTimeout(createInsect, 1000)
        startGame()
    })
})

// 开始游戏
function startGame() {
    setInterval(increaseTime, 1000)
}

// 开始计时
function increaseTime() {
    let m = Math.floor(seconds / 60)
    let s = seconds % 60
    m = m < 10 ? `0${m}` : m
    s = s < 10 ? `0${s}` : s
    timeEl.innerHTML = `Time: ${m}:${s}`
    seconds++
}
// 创建昆虫
function createInsect() {
    const insect = document.createElement('div')
    insect.classList.add('insect')
    const { x, y } = getRandomLocation()
    insect.style.top = `${y}px`
    insect.style.left = `${x}px`
    insect.innerHTML = `<img src="${selected_insect.src}" alt="${selected_insect.alt}" style="transform: rotate(${Math.random() * 360}deg)" />`

    insect.addEventListener('click', catchInsect)

    game_container.appendChild(insect)
}

// 创建昆虫出没的随机位置
function getRandomLocation() {
    const width = window.innerWidth
    const height = window.innerHeight
    const x = Math.random() * (width - 200) + 100
    const y = Math.random() * (height - 200) + 100
    return { x, y }
}

// 捕捉到了昆虫
function catchInsect() {
    increaseScore()
    this.classList.add('caught')
    setTimeout(() => this.remove(), 2000)
    addInsects()
}

// 创建新的昆虫
function addInsects() {
    setTimeout(createInsect, 1000)
    setTimeout(createInsect, 1500)
}

// 增加积分
function increaseScore() {
    score++
    if(score > 19) {
        message.classList.add('visible')
    }
    scoreEl.innerHTML = `Score: ${score}`
}

实现步骤:

  1. 单击"Play Game"按钮将切换到选择昆虫屏幕,并开始游戏。
  2. 单击昆虫选项后,游戏开始,创建飞行的昆虫,并启动游戏计时。
  3. 游戏计时会不断增加,分数随着捕捉昆虫的数量而增加。
  4. 游戏结束后,如果分数达到20,将显示一条消息。

CSS样式

🐯美化游戏界面。

游戏界面采用了像素风格的字体

css 复制代码
@import url('https://fonts.googleapis.com/css?family=Press+Start+2P&display=swap');
* {
  box-sizing: border-box;
}
body {
  background-color: #516dff;
  color: #fff;
  font-family: 'Press Start 2P', sans-serif;
  height: 100vh;
  overflow: hidden;
  margin: 0;
  text-align: center;
}
a {
  color: #fff;
}

h1 {
  line-height: 1.4;
}

按钮和选项有特定的样式,包括悬停和点击效果

css 复制代码
.btn {
  border: 0;
  background-color: #fff;
  color: #516dff;
  padding: 15px 20px;
  font-family: inherit;
  cursor: pointer;
}

.btn:hover {
  opacity: 0.9;
}

.btn:focus {
  outline: 0;
}

.screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  width: 100vw;
  transition: margin 0.5s ease-out;
}

.screen.up {
  margin-top: -100vh;
}

.insects-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  list-style-type: none;
  padding: 0;
}

.insects-list li {
  margin: 10px;
}

.choose-insect-btn {
  background-color: transparent;
  border: 2px solid #fff;
  color: #fff;
  cursor: pointer;
  font-family: inherit;
  width: 150px;
  height: 150px;
}

.choose-insect-btn:hover {
  background-color: #fff;
  color: #516dff;
}

.choose-insect-btn:active {
  background-color: rgba(255, 255, 255, 0.7);
}

.choose-insect-btn img {
  width: 100px;
  height: 100px;
  object-fit: contain;
}

游戏的时间

css 复制代码
.game-container {
  position: relative;
}
.time,
.score {
  position: absolute;
  top: 20px;
}

.time {
  left: 20px;
}

.score {
  right: 20px;
}

游戏中的昆虫具有动画效果,可以被单击捕捉。

css 复制代码
.insect {
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100px;
  height: 100px;
  position: absolute;
  transform: translate(-50%, -50%) scale(1);
  transition: transform 0.3s ease-in-out;
}

.insect.caught {
  transform: translate(-50%, -50%) scale(0);
}

.insect img {
  width: 100px;
  height: 100px;
}

游戏结束后,会显示一条消息。

css 复制代码
.message {
  line-height: 1.7;
  background-color: rgba(0, 0, 0, 0.5);
  width: 100%;
  padding: 20px;
  z-index: 100;
  text-align: center;
  opacity: 0;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -150%);
  transition: transform 0.4s ease-in;
}

.message.visible {
  transform: translate(-50%, 150%);
  opacity: 1;
}

总结:

这个小游戏是一个简单而有趣的互动体验,可以通过点击昆虫来尽情享受游戏的乐趣。

为什么代码那么全,是由于我认为大家有意想玩玩看。


😘完结撒花🌹🌹🌹🌹🌹🌹

相关推荐
速盾cdn23 分钟前
速盾:网页游戏部署高防服务器有什么优势?
服务器·前端·web安全
小白求学124 分钟前
CSS浮动
前端·css·css3
什么鬼昵称25 分钟前
Pikachu-csrf-CSRF(POST)
前端·csrf
golitter.42 分钟前
Vue组件库Element-ui
前端·vue.js·ui
儒雅的烤地瓜1 小时前
JS | JS中判断数组的6种方法,你知道几个?
javascript·instanceof·判断数组·数组方法·isarray·isprototypeof
道爷我悟了1 小时前
Vue入门-指令学习-v-on
javascript·vue.js·学习
27669582921 小时前
京东e卡滑块 分析
java·javascript·python·node.js·go·滑块·京东
golitter.1 小时前
Ajax和axios简单用法
前端·ajax·okhttp
PleaSure乐事1 小时前
【Node.js】内置模块FileSystem的保姆级入门讲解
javascript·node.js·es6·filesystem
雷特IT1 小时前
Uncaught TypeError: 0 is not a function的解决方法
前端·javascript