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

前言

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

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


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

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


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

目录

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

上期解析 6day-10day,项目展示。

本期解析 11day-15day,项目展示。

  • ✅ [Drink Water(喝杯水)](#Drink Water(喝杯水) "#heading-3")
  • ✅ [movie App(视频APP)](#movie App(视频APP) "#heading-6")
  • ✅ [Background Slider(背景滑块)](#Background Slider(背景滑块) "#heading-9")
  • ✅ [Theme Clock(主题时钟)](#Theme Clock(主题时钟) "#heading-12")
  • ✅ [Button Ripple Effect(按钮波纹效果)](#Button Ripple Effect(按钮波纹效果) "#heading-15")

下期解析 16day-20day,项目展示。

传送门🚀

16、Drink Water(喝杯水)

主要关注点:大杯水量变化与小杯的连续选中与取消问题。

实现效果:

用户打开页面后,能够看到标题"Drink Water"和目标饮水量为2升的提示。页面中有一组250毫升的小水杯,用户可以点击这些小水杯来记录已饮水量。每次点击小水杯,大水杯的显示状态会更新,显示已饮水量的百分比,以及剩余的升数。页面使用了一定的CSS样式来美化界面。

实现关键代码

HTML 结构:页面的结构包括标题、目标饮水量的提示、大水杯、小水杯列表以及用于显示剩余水量的元素。

html 复制代码
<div class="cup">
      <div class="remained" id="remained">
        <span id="liters"></span>
        <small>Remained</small>
      </div>

      <div class="percentage" id="percentage"></div>
    </div>
     <!--省略-->
    <div class="cups">
      <div class="cup cup-small">250 ml</div>
      <div class="cup cup-small">250 ml</div>
      <!--省略-->
    </div>

JavaScript 逻辑:获取元素、初始化状态、为小水杯添加点击事件监听器、处理按键事件、更新页面显示等

看一下注释

js 复制代码
// 获取所有小水杯元素 
const smallCups = document.querySelectorAll('.cup-small') 
// 获取剩余水量、百分比和剩余部分的元素 
const liters = document.getElementById('liters') 
const percentage = document.getElementById('percentage') 
const remained = document.getElementById('remained')

// 为每个小水杯添加点击事件监听器 
// 注意:两个循环最好不要嵌套,拉出一个新函数
smallCups.forEach((cup, idx) => { 
    cup.addEventListener('click', () => highlightCups(idx))
}

// 处理小水杯点击事件的函数
function highlightCups(idx) {
    // 如果当前点击的是第 8 杯且已经满了,将索引减 1,确保不会超出范围
    if (idx===7 && smallCups[idx].classList.contains("full")) idx--;
    // 如果当前小水杯已满且下一个小水杯未满,将索引减 1,确保不会跳过未满的小水杯
    else if(
    smallCups[idx].classList.contains('full') && !smallCups[idx].nextElementSibling.classList.contains('full')) {
        idx--
    }
    // 遍历所有小水杯,更新它们的状态
    smallCups.forEach((cup, idx2) => {
        if(idx2 <= idx) {
            cup.classList.add('full')
        } else {
            cup.classList.remove('full')
        }
    })
    // 更新大水杯的状态和显示
    updateBigCup()
}

// 更新大水杯状态和显示的函数
function updateBigCup () {
  // 获取已满的小水杯数量和总小水杯数量
  const fullCups = document.querySelectorAll('.cup-small.full').length
  const totalCups = smallCups.length

  // 根据已饮水杯数量更新百分比条形图的显示
  if (fullCups === 0) {
    percentage.style.visibility = 'hidden'
    percentage.style.height = 0
  } else {
    percentage.style.visibility = 'visible'
    percentage.style.height = `${fullCups / totalCups * 330}px`
    percentage.innerText = `${fullCups / totalCups * 100}%`
  }

  // 如果已饮水杯数量等于总水杯数量,隐藏剩余水量部分
  if (fullCups === totalCups) {
    remained.style.visibility = 'hidden'
    remained.style.height = 0
  } else {
    // 否则显示剩余水量部分,并计算剩余水量并显示
    remained.style.visibility = 'visible'
    liters.innerText = `${2 - (250 * fullCups / 1000)}L`
  }
}

实现步骤:

  1. 获取元素: 在开始执行逻辑之前,首先获取需要操作的元素,包括小水杯、剩余水量、百分比和剩余部分的元素。
  2. 初始化大水杯状态: 在页面加载后,调用 updateBigCup 函数来初始化大水杯的状态和显示,以确保初始状态正确。
  3. 为小水杯添加点击事件监听器: 使用 forEach 循环为每个小水杯元素添加点击事件监听器,这样当用户点击小水杯时,将会调用 highlightCups 函数来处理点击事件。
  4. 处理点击事件:highlightCups 函数中,首先处理点击事件的逻辑。根据用户点击的小水杯的位置,更新其他小水杯的状态,以确保状态正确。
  5. 更新大水杯状态:highlightCups 函数内调用 updateBigCup 函数,以更新大水杯的状态和显示,以反映最新的饮水量状态。
  6. 更新大水杯百分比和剩余水量显示:updateBigCup 函数内,通过计算已饮水杯数量和总杯数,更新百分比条形图的高度和显示。如果已饮水满,隐藏剩余水量部分,否则计算并显示剩余水量。

CSS样式

🐯水杯水量的变化:定义了页面的样式,包括水杯、文本等外观。

css 复制代码
.percentage {
  background-color: var(--fill-color);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  font-size: 30px;
  height: 0;  /* 高度为0,主要靠js修改高度,动画来源于transition*/
  transition: 0.3s ease;
}

总结:

上面的代码实现了一个"Drink Water"(喝水)的页面应用,允许用户通过点击小水杯来记录已饮水量,同时大水杯的状态会根据饮水量的百分比进行更新显示,剩余水量也会显示出来。

点击后面的杯子,前面的杯子也会被添加full,点击前面的满杯,后面的杯子也会被移除full,每一次的操作都要对大杯进行更新。

17、movie App(视频APP)

主要关注点:关于html的api的运用、电影搜索应用的实现

实现效果:

该应用通过调用 The Movie Database 的 API,从中获取电影信息并显示在页面上。用户可以搜索电影,查看电影海报、评分和概述。

实现关键代码

HTML 结构:页面主要由一个搜索框和一个用于显示电影信息的主区域构成。

html 复制代码
<header>
  <form id="form">
    <input type="text" id="search" class="search" placeholder="Search">
  </form>
</header>

<main id="main"></main>

JavaScript 逻辑:实现获取电影信息、显示电影、处理评分等功能。

js 复制代码
const API_URL = 'https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=3fd2be6f0c70a2a598f084ddfb75487c&page=1'
const IMG_PATH = 'https://image.tmdb.org/t/p/w1280'
const SEARCH_API = 'https://api.themoviedb.org/3/search/movie?api_key=3fd2be6f0c70a2a598f084ddfb75487c&query="'

const main = document.getElementById('main')
const form = document.getElementById('form')
const search = document.getElementById('search')

// 获取初始电影
getMovies(API_URL)

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 } = movie
        const movieEl = document.createElement('div')
        // ...
        main.appendChild(movieEl)
    })
}

function getClassByRate(vote) {
    // 根据评分获取不同的 CSS 类名
    if(vote >= 8) {
        return 'green'
    } else if(vote >= 5) {
        return 'orange'
    } else {
        return 'red'
    }
}

// 搜索表单提交事件监听
form.addEventListener('submit', (e) => {
    e.preventDefault()

    const searchTerm = search.value

    if(searchTerm && searchTerm !== '') {
        // 根据搜索词获取电影信息并显示
        getMovies(SEARCH_API + searchTerm)

        search.value = ''
    } else {
        // 重新加载页面
        window.location.reload()
    }
})

实现步骤:

  1. 获取电影数据: 使用 themoviedb API 获取电影数据,主要关注热门电影的排序。
  2. 展示电影: 使用 showMovies 函数将电影数据渲染到页面上,包括电影海报、评分和概述。
  3. 评分样式: 使用 getClassByRate 函数根据评分判断并返回不同的 CSS 类名,用于显示不同的评分颜色。
  4. 搜索功能: 通过 form 元素的提交事件监听,在搜索框中输入关键词后,通过 TMDb API 搜索电影,并在页面上显示匹配的电影。
  5. 重新加载页面: 如果搜索框为空或只包含空格,则通过重新加载页面来重置搜索状态。

CSS样式

🐯页面:提供了页面的样式,包括搜索框、电影海报、评分等的样式。

主要关心:鼠标移动在movie上面,出现的简介形式

css 复制代码
.overview {
  background-color: #fff;
  padding: 2rem;
  position: absolute;
  left: 0;
  bottom: 0;
  right: 0;
  max-height: 100%;
  transform: translateY(101%);
  overflow-y: auto;
  transition: transform 0.3s ease-in;
}

.movie:hover .overview {
  transform: translateY(0);
}

总结:

电影搜索应用充分利用了 API 数据获取和展示、事件监听和处理以及动态样式变化等前端开发技术。用户可以轻松地搜索电影信息,查看评分和概述,为电影爱好者提供了便捷的交互式体验。

利用overflow隐藏初始化的overview标签,采用transform: translateY(101%)隐藏起来,在触发moviehover时候overview移动到transform: translateY(0)

18、Background Slider(背景滑块)

主要关注点:背景的展示、滑动逻辑。

实现效果:

创建一个背景幻灯片,用户可以点击左右箭头按钮切换不同的背景图片,实现视觉上的幻灯片切换效果。

实现关键代码

HTML 结构:创建了幻灯片容器和箭头按钮

html 复制代码
<div class="slider-container">
  <div class="slide active" style="background-image: url('...');"></div>
  <div class="slide" style="background-image: url('...');"></div>
  <!-- 其他幻灯片项 -->
  <button class="arrow left-arrow" id="left">
    <i class="fas fa-arrow-left"></i>
  </button>
  <button class="arrow right-arrow" id="right">
    <i class="fas fa-arrow-right"></i>
  </button>
</div>

JavaScript 逻辑:通过按钮点击事件切换幻灯片和更新背景图片

js 复制代码
// 获取页面元素
const body = document.body; // 页面 body 元素
const slides = document.querySelectorAll('.slide'); // 获取所有幻灯片元素
const leftBtn = document.getElementById('left'); // 左箭头按钮
const rightBtn = document.getElementById('right'); // 右箭头按钮

let activeSlide = 0; // 当前激活的幻灯片索引

// 右箭头按钮点击事件
rightBtn.addEventListener('click', () => {
  activeSlide++;

  // 如果当前索引超过幻灯片数量,回到第一张
  if (activeSlide > slides.length - 1) {
    activeSlide = 0;
  }

  setBgToBody(); // 更新页面背景图片
  setActiveSlide(); // 设置当前激活的幻灯片
});

// 左箭头按钮点击事件
leftBtn.addEventListener('click', () => {
  activeSlide--;

  // 如果当前索引小于 0,回到最后一张
  if (activeSlide < 0) {
    activeSlide = slides.length - 1;
  }

  setBgToBody(); // 更新页面背景图片
  setActiveSlide(); // 设置当前激活的幻灯片
});

// 初始化页面背景图片
setBgToBody();

// 更新页面背景图片
function setBgToBody() {
  body.style.backgroundImage = slides[activeSlide].style.backgroundImage;
}

// 设置当前激活的幻灯片
function setActiveSlide() {
  slides.forEach((slide) => slide.classList.remove('active')); // 移除所有幻灯片的激活状态

  slides[activeSlide].classList.add('active'); // 添加当前幻灯片的激活状态
}

实现步骤:

  1. 创建HTML结构,包括幻灯片容器和箭头按钮。
  2. 使用JavaScript监听按钮点击事件,切换幻灯片和更新背景图片。
  3. 实现动态切换背景图片,为用户提供视觉上的幻灯片切换效果。

完成的样式效果

html 复制代码
<body style="
background-image: url('...a');
">
  <div class="slider-container">
    <div
      class="slide active"
      style="
        background-image: url('...a');
      "
    ></div>
  </div>
</body>

CSS样式

🐯底部图片:底部加上遮罩层、图片铺开、动画效果。

css 复制代码
body {
  font-family: 'Roboto', sans-serif;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  overflow: hidden;
  margin: 0;
  background-position: center center;
  background-size: cover;
  transition: 0.4s;
}

body::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.7);
  z-index: -1;
}

🐯高亮图片:定义了幻灯片容器的样式,包括盒阴影、尺寸、位置等

css 复制代码
.slider-container {
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
   // 给出height与width,hidden后内部的元素再折腾也就显示出来那么多
  height: 70vh;
  width: 70vw;
  position: relative;
  overflow: hidden;
}

.slide {
  opacity: 0;
  /* 图片100%的张开了,大小与body里的图片一样 */
  height: 100vh;
  width: 100vw;
  background-position: center center;
  background-size: cover;
  position: absolute;
   /* 再高亮的区域内部上移15vh很合理,因为上方就有15vh */
  /* (100vh - 70vh) / 2 = 15vh*/
  top: -15vh;
  left: -15vw;
  transition: 0.4s ease;
  z-index: 1;
}

.slide.active {
  opacity: 1;
}

总结:

这段代码实现了一个背景幻灯片效果,用户可以通过点击左右箭头按钮切换不同的背景图片,从而实现视觉上的幻灯片切换效果。JavaScript监听按钮点击事件,根据用户操作切换幻灯片,并实时更新页面背景图片,为用户提供了一种美观的页面交互体验。

对于上下图片重合显示问题: 在body中加入的图片height: 100vh;的展示,而在.slider-container中是height: 70vh;width: 70vw;的展示,加上隐藏超出的数据,所有在.slide中的需要填满body使用(100vh - 70vh) / 2 = 15vh,上下都差15到边沿 为什么? 看图

所以slide采用了

css 复制代码
position: absolute;
top: -15vh;
left: -15vw;

19、Theme Clock(主题时钟)

主要关注点:全局的颜色变化

实现效果:

创建一个时钟,包括时、分、秒的指针,以及日期和主题切换按钮。可以切换亮色和暗色两种主题。

实现关键代码

HTML 结构:创建时钟的样式

html 复制代码
<button class="toggle">Dark mode</button>

<div class="clock-container">
  <div class="clock">
    <div class="needle hour"></div>
    <div class="needle minute"></div>
    <div class="needle second"></div>
    <div class="center-point"></div>
  </div>

  <div class="time"></div>
  <div class="date"></div>
</div>

JavaScript 逻辑:切换黑白、定时处理时间函数

切换黑白颜色

js 复制代码
toggle.addEventListener('click', (e) => {
    const html = document.querySelector('html')
    if (html.classList.contains('dark')) {
        html.classList.remove('dark')
        e.target.innerHTML = 'Dark mode'
    } else {
        html.classList.add('dark')
        e.target.innerHTML = 'Light mode'
    }
})

时间显示

js 复制代码
function setTime() {
    const time = new Date();
    const month = time.getMonth()
    const day = time.getDay()
    const date = time.getDate()
    const hours = time.getHours()
    const hoursForClock = hours >= 13 ? hours % 12 : hours;
    const minutes = time.getMinutes()
    const seconds = time.getSeconds()
    const ampm = hours >= 12 ? 'PM' : 'AM'

    hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 12, 0, 360)}deg)`
    minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 60, 0, 360)}deg)`
    secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 60, 0, 360)}deg)`

    timeEl.innerHTML = `${hoursForClock}:${minutes < 10 ? `0${minutes}` : minutes} ${ampm}`
    dateEl.innerHTML = `${days[day]}, ${months[month]} <span class="circle">${date}</span>`
}

// 这个是角度
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;
}

setTime()

setInterval(setTime, 1000)

实现步骤:

  1. 创建一个按钮元素,用于切换主题。
  2. 创建一个时钟容器,包含时钟指针、时间和日期元素。
  3. 使用 JavaScript 获取页面元素,设置切换主题功能,以及更新时钟的时间和日期。
  4. 定义时间和日期的格式,并设置时、分、秒指针的位置。
  5. 创建一个函数用于进行数值映射。
  6. 初始化时钟并使用 setInterval 每秒钟更新一次时间。

CSS样式

🐯黑白颜色:切换黑白颜色需要的样式

css 复制代码
// 规划颜色
:root {
  --primary-color: #000;
  --secondary-color: #fff;
}

html {
  transition: all 0.5s ease-in;
}

// 给html写了两个全新的变量
html.dark {
  --primary-color: #fff;
  --secondary-color: #333;
}

// 设计在toggle中dark下的颜色
html.dark {
  background-color: #111;
  color: var(--primary-color);
}

// 下面的颜色都使用变量来设计

总结:

本代码实现了一个主题切换功能的时钟。通过点击按钮可以切换亮色和暗色两种主题,时钟包含了时、分、秒指针,以及日期显示。JavaScript 控制时钟的更新和主题切换,样式为时钟提供了美观的外观。整体效果为一个实用且富有设计感的时钟应用。

利用scale的方法,获取到当前时间 时秒分 的角度,setInterval(setTime, 1000),每一秒执行一次执行函数。

togglehtml添加class类,来控制变量颜色。

20、Button Ripple Effect(按钮波纹效果)

主要关注点:按钮点击产生水波纹效果展示

实现效果:

创建一个按钮,当点击按钮时,按钮上产生水波纹扩散效果。

实现关键代码

HTML 结构:构建方块

html 复制代码
<button class="ripple">Click Me</button>

JavaScript 逻辑:获取点击的位置

js 复制代码
const buttons = document.querySelectorAll('.ripple')

buttons.forEach(button => {
    button.addEventListener('click', function (e) {
        const x = e.pageX
        const y = e.pageY

        const buttonTop = e.target.offsetTop
        const buttonLeft = e.target.offsetLeft

        const xInside = x - buttonLeft
        const yInside = y - buttonTop

        const circle = document.createElement('span')
        circle.classList.add('circle')
        circle.style.top = yInside + 'px'
        circle.style.left = xInside + 'px'

        this.appendChild(circle)

        setTimeout(() => circle.remove(), 500)
    })
})

实现步骤:

  1. 创建一个按钮元素,标记为具有水波纹效果的类名 ripple
  2. 使用 JavaScript 获取所有具有 .ripple 类名的按钮元素。
  3. 对每个按钮添加点击事件监听器,在点击时创建一个 <span> 元素,表示水波纹效果。
  4. 根据点击位置计算水波纹的位置,并将其添加到按钮内部。
  5. 通过定时器,在一段时间后移除水波纹元素。

CSS样式

🐯关键样式:定义了按钮的样式以及水波纹效果的动画。

css 复制代码
button .circle {
  position: absolute;
  background-color: #fff;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0);
  animation: scale 0.5s ease-out;
}

@keyframes scale {
  to {
    transform: translate(-50%, -50%) scale(3);
    opacity: 0;
  }
}

总结:

本代码实现了一个按钮点击产生水波纹效果的功能。通过 JavaScript 监听按钮点击事件,利用<span/>的画圆形图,在按钮上产生一个水波纹扩散的动画效果,通过添加和移除 <span> 元素来实现。按钮的样式以及水波纹的动画效果使得按钮点击更加有趣且生动。


😘预知后事如何,待下回分解

相关推荐
gnip18 分钟前
链式调用和延迟执行
前端·javascript
SoaringHeart29 分钟前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.31 分钟前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频
Dragon Wu41 分钟前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
Jinuss42 分钟前
Vue3源码reactivity响应式篇之watch实现
前端·vue3
YU大宗师1 小时前
React面试题
前端·javascript·react.js
木兮xg1 小时前
react基础篇
前端·react.js·前端框架
ssshooter1 小时前
你知道怎么用 pnpm 临时给某个库打补丁吗?
前端·面试·npm
IT利刃出鞘2 小时前
HTML--最简的二级菜单页面
前端·html
yume_sibai2 小时前
HTML HTML基础(4)
前端·html