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

前言

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

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


50projects50days项目地址:?????

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


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

目录

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

1691734552579.jpg

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

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

下期解析 21day-25day,项目展示。

传送门?

16、Drink Water(喝杯水)

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

实现效果:

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

实现关键代码

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

看一下注释

// 获取所有小水杯元素 
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样式

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

.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 结构:页面主要由一个搜索框和一个用于显示电影信息的主区域构成。

<header>
  <form id="form">
    <input type="text" id="search" class="search" placeholder="Search">
  </form>
</header>




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

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

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上面,出现的简介形式

.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(背景滑块)

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

实现效果:

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

3.gif

实现关键代码

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 逻辑:通过按钮点击事件切换幻灯片和更新背景图片

// 获取页面元素
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. 实现动态切换背景图片,为用户提供视觉上的幻灯片切换效果。

完成的样式效果

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





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;
}

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

.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到边沿
为什么?
看图

image.png

所以slide采用了

position: absolute;
top: -15vh;
left: -15vw;

19、Theme Clock(主题时钟)

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

实现效果:

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

实现关键代码

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 逻辑:切换黑白、定时处理时间函数

切换黑白颜色

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'
    }
})

时间显示

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样式

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

// 规划颜色
: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 结构:构建方块

<button class="ripple">Click Me</button>

JavaScript 逻辑:获取点击的位置

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样式

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

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> 元素来实现。按钮的样式以及水波纹的动画效果使得按钮点击更加有趣且生动。


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

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYKdgx6V' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片