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

前言

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

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


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

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


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

目录

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

上期解析 26day-30day,项目展示。

本期解析 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,项目展示。

传送门🚀

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

实现步骤:

  1. 设计一手,用户可以设置密码的长度以及包含的字符类型的界面。
  2. 点击 "Generate Password" 按钮将生成密码并显示在页面上,利用函数与传入的字符长度,来确定随机的内容。
  3. 点击调用方法 navigator.clipboard.writeText("内容") ,剪贴板图标可以将密码复制到剪贴板。

CSS样式

🐯CSS样式用于美化页面和界面元素的样式,使其看起来更吸引人

有点意思的是字体图标的引入 <i class="far fa-clipboard"></i>

css 复制代码
@import url('https://fonts.googleapis.com/css?family=Muli&display=swap');

总结:

这个密码生成器实现了一个简单而实用的功能,用户可以轻松地生成自定义密码并将其复制到剪贴板。但是,这个复制仅仅适用于web,如果是 H5webview 的环境,注意复制文字的兼容性问题。

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

实现步骤:

  1. 用户可以选择他们三项中的两项。
  2. 如果用户选择了其中两项,系统会自动取消未选择的那一项。
  3. 页面中的开关按钮会在用户点击后切换状态,并通过动画效果显示用户的选择。

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>的效果

通过一个函数添加那么多相同的节点,删除的则也是自己点击的节点。

实现步骤:

  1. 用户可以点击 Add note 按钮来添加新的笔记。
  2. 每个笔记都有编辑和删除按钮,用户可以编辑笔记内容。
  3. 笔记支持 Markdown 格式,实时预览。
  4. 笔记会被保存到本地存储,以便用户下次访问时仍可见。

CSS样式

🐯XXXXXXXX:定义了XXXXXXXX。

css 复制代码
.hidden {
  display: none;
}

在类 maintextarea 标签中,来回切换

总结:

这个笔记应用允许用户方便地管理笔记,支持 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()
})

实现步骤:

  1. 页面加载时自动开始倒计时,从 3 倒数到 0 。
  2. 倒计时数字具有动画效果,依次显示和隐藏。
  3. 当倒计时完成后,显示 "GO" 和 "Replay" 按钮。
  4. 用户可以点击 "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()
})

实现步骤:

  1. 页面加载时自动开始图片轮播,每2秒切换一张图片。
  2. 用户可以点击 "Prev" 和 "Next" 按钮手动切换图片,点击按钮后会重置自动轮播定时器。
  3. 图片循环轮播,切换到最后一张后回到第一张。
  4. 利用 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;
}

总结:

这个图片轮播页面提供了交互性,用户可以点击按钮或自动轮播来浏览不同的图片。


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

相关推荐
m0_7482550227 分钟前
前端常用算法集合
前端·算法
真的很上进41 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203981 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2341 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1232 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~3 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语3 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport3 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg3 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww3 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest