iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
Modern Web

30天30個前端任務系列 第 7

#6. Scroll Animation(原生JS版), #7. Progress Steps(原生JS版)

Scroll Animation 卡片滑動載入效果(原生JS版)

CodePen: https://codepen.io/zyrxdkoz/pen/dyROrLB

實作邏輯

javacript

// 選取所有.box
const boxes = document.querySelectorAll('.box')
window.addEventListener('scroll', checkBoxes)

checkBoxes()

function checkBoxes () {
  // 取得啟動點,取在視窗高度的五分之一位置
  const triggerBottom = window.innerHeight / 5 * 4

  // 用forEach處理每個box
  boxes.forEach(box => {
    // 運用getBoundingClientRect方法找出viewport與element的距離
    const boxTop = box.getBoundingClientRect().top
    
    // 如boxTop比啟動點小,就加入show選擇器否則取消
    if (boxTop < triggerBottom) {
      box.classList.add('show')
    } else {
      box.classList.remove('show')
    }
  })
}

CSS部分(節錄)

.box {
  background-color: steelblue;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 400px;
  height: 200px;
  margin: 10px;
  border-radius: 10px;
  box-shadow: 2px 4px 5px rgba(0, 0, 0, 0.3);
  
  // 預設位置是左移400%
  transform: translateX(400%);
  transition: transform 0.4s ease;
  
  // 順序為奇數的box項目,則是右移400%
  &:nth-of-type(even) {
    transform: translateX(-400%);
  }
  h2 {
    font-size: 45px;
  }
  &.show {
    // 加入show選擇器時,返回到畫面中央
    transform: translateX(0);
  }

Progress Steps 進度條按鈕(原生JS版)

CodePen: https://codepen.io/zyrxdkoz/pen/rNwWgrM

實作邏輯

javacript

const prev = document.getElementById('prev')
const next = document.getElementById('next')
const circles = document.querySelectorAll('.circle')
const progress = document.getElementById('progress')
const actives = document.querySelectorAll('.active')

let currentActive = 1

// next按鈕行為
next.addEventListener('click', () => {
  currentActive++
  // 讓currentActive數值與circles.length同步
  if (currentActive > circles.length) { currentActive = circles.length }
  update()
})

// prev按鈕行為
prev.addEventListener('click', () => {
  currentActive--
  // 讓currentActive數值與circles.length同步
  if (currentActive < 1) { currentActive = 1 }
  update()
})

function update () {
  // 用currentActive逐一比對每個circle的序數,作出相應行為
  circles.forEach((circle, idx) => {
    if (idx < currentActive) {
      circle.classList.add('active')
    } else {
      circle.classList.remove('active')
    }
  })
  const actives = document.querySelectorAll('.active')
  
  // 計算progress的長度(預設為0%)
  // 初始值:分母是4 - 1,分子是1 - 1
  // 第一次按next: 分母是4 - 1,分子是2 - 1,相當於33%
  // 第二次按next: 分母是4 - 1,分子是3 - 1,相當於66%
  progress.style.width = (actives.length - 1) / (circles.length - 1) * 100 + '%'
  
  // 判斷何時要將按鈕做disable處理
  if (currentActive === 1) {
    prev.disabled = true
  } else if (currentActive === circles.length) {
    next.disabled = true
  } else {
    prev.disabled = false
    next.disabled = false
  }
}

明日任務

  1. Q&A Section (Vue版本)
  2. Button Ripple Effect (JS原生版)

上一篇
#5. Q&A Section(原生JS版)、#2. Blurring Loading(Vue版)、#3. Expanding Cards(Vue版)
下一篇
#8 Button Ripple Effect(原生JS版)、#5. Q&A Section(Vue版)
系列文
30天30個前端任務19

尚未有邦友留言

立即登入留言