CSS 및 JavaScript 클론 hey-pin 메뉴 사용

27854 단어 uicssjavascript

Note: this post was originally published on my personal blog


웹 개발의 기초를 강화하거나 우수한 전단 개발자가 되는 가장 좋은 방법은 HTML, CSS와 자바스크립트를 대량으로 연습하는 것이다. 이런 기술을 배우는 가장 좋은 방법은 그들을 이용하여 많은 보조 프로젝트를 만드는 것이다. 이것이 바로 내가 일련의 새로운 블로그를 시작하기로 결정한 이유이다. 이런 블로그들은 작은 부분의 작업 UI 구성 요소를 구축하는 간단한 생각을 실현했다.대부분의 경우 vanilla JavaScript, vanilla CSS 및 일반 HTML 태그가 사용됩니다.

본고에서 나는 헤이의 핀 메뉴 (set-aside 메뉴) 복제를 통해 나의 첫 번째 도전을 시작할 것이다.com 사이트에서 저는 무료 시용을 했습니다. 탐색을 한 후에 저는 그곳에 좋은 디자인 결정이 많다는 것을 발견했습니다. 그러나 가장 아픈 것은 그들이 전자메일을 위해 실시하는pin 메뉴입니다. 전자메일을 방문하는 단축 방식으로서 그 목적이 무엇이든지 위의 예시에서 보듯이 저는 이 생각을 좋아합니다. 그리고 그것을 복제하고 사본을 만들기로 결정했습니다.

가설


다음과 같이 순수 JavaScript에 로드된 데이터 배열을 제공합니다.
const listOfItems = [
  "semicolon.academy",
  "twitter@SemicolonA",
  "FB.com/semicolonAcademy",
  "YT.com/SemicolonAcademy",
  "twitter@med7atdawoud",
  "IG/medhatdawoud",
  "medhatdawoud.net",
]

const stack = document.getElementById("stack")
for (let i = 0; i < listOfItems.length; i++) {
  let div = document.createElement("div")
  div.classList.add("single-block")
  div.innerHTML = `
      <div class="content">
        <img src="${path / to / heyLogo}" />
        <div><h3>${listOfItems[i]}</h3><p>description</p></div>
      </div>`
  stack.append(div)
}
11줄부터 20줄까지 우리는normal for 문장이 있습니다. 그 안에 우리는 매번div 요소를 만들고 클래스single-block를 줍니다. 이 클래스는 데이터 블록의 스타일을 응용하는 데 사용되기 때문에hey와 유사합니다.com 메뉴 항목.stack 줄에서 선택한 11 은 HTML 파일의 div입니다. 전체 디자인을 저장하고 모든 CSS는 뒤에 있는 전체 예시에서 제공됩니다 (일단 걱정하지 마십시오).
지금 저희가 다음과 같은 결과를 얻었습니다.

이것은 시작 상태로 볼 수 있다. 여기서 우리는 다음과 같은 도전을 이해해야 한다.

도전하다


1 - 상술한 항목 목록을 창고처럼 보입니다.
2 - 클릭할 때 확장된 동작을 수행합니다.
3 - 스택을 제외한 모든 컨텐트를 클릭하고 되돌려야 합니다(축소).

실시


1 - 우선, 우리는 이를div 목록에서 창고로 변환합니다.
div 목록을 창고 보기로 바꾸려면 CSS를 사용해야 합니다. 우선, 저는 창고가 div 목록으로 보인다고 상상할 수 있습니다. 이 div들은 서로 다른 층에 위치하고 각각의 div는 서로 다른 위치를 가지고 있기 때문에 다음은 우리가 일반적으로 추가해야 할 CSS 목록입니다.
body {
  font-family: sans-serif;
  font-size: 16px;
}

#stack {
  position: absolute;
  height: 80vh;
  bottom: 30px;
  left: 40%;
  text-align: center;
  cursor: pointer;
}

.single-block {
  position: absolute;
  bottom: 0;
  background: #fff;
  box-shadow: 0 0 10px #eee;
  border-radius: 10px;
  transition: ease-in-out 0.2s;
}

.single-block .content {
  display: flex;
  padding: 11px 20px 9px;
}

.single-block .content img {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
}

.single-block .content > div {
  text-align: left;
  margin-left: 10px;
  width: 180px;
}

.single-block .content h3 {
  margin: 0;
  font-size: 16px;
  font-weight: normal;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.single-block .content p {
  color: #aaa;
  margin: 0;
}
현재 css의 transform 속성이 있습니다. 우리는 여기저기 놀 수 있습니다. 왜냐하면transform을 사용하면 프로젝트를 위아래로 축소할 수 있고 Y축에서 평평하게 옮길 수 있습니다. 이것은 바로 우리가 하고 싶은 것입니다. 그러나 우리는 자바스크립트에 이 스타일을 추가해야 합니다. 이것은 어쨌든 프로젝트의 순서에 달려 있기 때문입니다.
기본적으로 우리는 1의 비율로 첫 번째 항목을 시작하고 0를 다음과 같이 번역할 것이다
transform: scale(1) translateY(0);
위의 CSS를 사용하면 목록에 있는 모든 항목에 주입할 수 있지만 서로 다른 확대/축소 및 변환 값을 사용하여 수학 연산을 한 결과 확대/축소 값이 0.033333333 이기 때문에 각 항목의 값은 이전의 값보다 작아야 한다고 생각합니다. 마찬가지로 Y축의 평이에 대한 값은 각 항목의 확대/축소 값과 같습니다0.7.
또한 우리의referent(hey.compin 메뉴)에 따라 항목은 반대로 표시해야 하기 때문에 반대로 표시해야 합니다. 반대로 색인을 얻기 위해서는 for문장의 다음 줄이 필요합니다.
const reverseIndex = listOfItems.length - 1 - i
현재 우리는 그것을 모든 항목의 변체로 사용할 수 있으며, 항목을 추가하기 전에 추가된 최종 코드는
const baseScaleChange = 0.033333333
const baseTranslateChange = 0.7
const reverseIndex = listOfItems.length - 1 - i
div.style.transform = `scale(${1 - reverseIndex * baseScaleChange}) 
     translateY(-${baseTranslateChange * reverseIndex}rem)`
추가 줄에 적용하기 전의 코드를 사용한 후에 우리는 다음과 같은 결과를 얻어야 한다

2 - 이제 다음 작업을 시작하고 스택을 클릭하여 확장합니다.
이를 위해 우리는 기본적으로transform 속성에 대해 작은 변경을 해야 한다. 이런 상황에서 우리는 모든 항목을 X축과 Y축에서 특정한 값으로 평이하게 해야 하고transform 속성에서 제공하는 rotate 함수를 사용하여 프로젝트 목록에서 이 곡선을 그려야 한다.
나는 다시 수학 연산을 했다. 회전 변화는 1.1, x 변화의 평이는 0.4 항목마다, 마지막 Y의 평이는 4 항목마다, 그리고 한마디로 함수translate를 사용할 수 있다. 첫 번째 매개 변수는 x의 값이고, 두 번째는 Y의 값이다.이 모든 것을 적용하기 위해서, 이 창고 div의 클릭 이벤트를 감청하고, 현재 사용 가능한 목록에서 순환해서 적용해야 합니다. 아래와 같습니다.
stack.addEventListener("click", function(e) {
  const blocks = this.querySelectorAll(".single-block")
  blocks.forEach((block, i) => {
    const reverseindex = blocks.length - 1 - i
    block.style.transform = `rotate(${reverseindex * 1.1}deg) 
    translate(-${reverseindex * 0.2}rem, -${reverseindex * 4}rem)`
  })
})
나는 코드가 스스로 해석할 수 있다고 생각하기 때문에 이 부분에 너무 많은 시간을 들일 수는 없지만, 지금은 코드를 추가하고 창고div를 클릭한 후에 모든 항목이hey의 행위처럼 전개되어야 한다.com 메뉴.
3 - 이제 마지막 미션에 도달해서 메뉴를 다시 접습니다.
우리는 이 점을 쉽게 할 수 있다. 우리가 이전에 프로젝트에 대해 한 것처럼 클릭 이벤트 ondocument을 들으면 다음과 같다.
document.addEventListener("click", function(e) {
  const blocks = document.querySelectorAll(".single-block")
  blocks.forEach((block, i) => {
    const reverseIndex = listOfItems.length - 1 - i
    block.style.transform = `scale(${1 - reverseIndex * baseScaleChange}) 
      translateY(-${baseTranslateChange * reverseIndex}rem)`
  })
})
실제로 상기 코드를 추가한 후에 메뉴 확장 자체가 작동하지 않습니다.왜냐하면 Event Bubbling 창고 div에 클릭 이벤트를 적용한 다음에 그 아버지 대상에 이벤트를 적용한 다음에 그 아버지 대상에 이벤트를 적용한다. 문서 요소가 우리가 방금 실현한 클릭 이벤트를 실현할 때까지 이 이벤트는 우리가 창고를 눌렀을 때와 완전히 상반된다.따라서 우리는 거품의 발생을 막아야 한다. 매우 간단한 해결 방안은 이벤트 처리의 시작 부분에서stackdiv click에 다음 줄을 추가하는 것이다.
e.stopPropagation()
이렇게 하면 js 파일의 최종 코드는 다음과 같습니다.
const heyLogoSrc =
  "https://production.haystack-assets.com/assets/avatars/defaults/hey-84b6169bf4060a76a94a072fe96b5fef7970b02d19507e2ab3952c042c21b154.svg"
const listOfItems = [
  "semicolon.academy",
  "twitter@SemicolonA",
  "FB.com/semicolonAcademy",
  "YT.com/SemicolonAcademy",
  "twitter@med7atdawoud",
  "IG/medhatdawoud",
  "medhatdawoud.net",
]

const baseScaleChange = 0.033333333
const baseTranslateChange = 0.7
document.addEventListener("DOMContentLoaded", function() {
  const stack = document.getElementById("stack")
  for (let i = 0; i < listOfItems.length; i++) {
    let div = document.createElement("div")
    div.classList.add("single-block")
    div.innerHTML = `
      <div class="content">
        <img src="${heyLogoSrc}" />
        <div><h3>${listOfItems[i]}</h3><p>description</p></div>
      </div>`
    const reverseIndex = listOfItems.length - 1 - i
    div.style.transform = `scale(${1 -
      reverseIndex * baseScaleChange}) translateY(-${baseTranslateChange *
      reverseIndex}rem)`
    stack.append(div)
  }

  stack.addEventListener("click", function(e) {
    e.stopPropagation()
    const blocks = this.querySelectorAll(".single-block")
    blocks.forEach((block, i) => {
      const reverseindex = blocks.length - 1 - i
      block.style.transform = `rotate(${reverseindex *
        1.1}deg) translate(-${reverseindex * 0.2}rem, -${reverseindex * 4}rem)`
    })
  })

  document.addEventListener("click", function(e) {
    const blocks = document.querySelectorAll(".single-block")
    blocks.forEach((block, i) => {
      const reverseIndex = listOfItems.length - 1 - i
      block.style.transform = `scale(${1 -
        reverseIndex * baseScaleChange}) translateY(-${baseTranslateChange *
        reverseIndex}rem)`
    })
  })
})
기본적으로 이렇다. 우리가 실현한 것은 위에서 실현한 것과 매우 가깝다.com 사이트.

결과와 결론


이제 우리는 도전을 완성했고 최종 결과는 다음과 같다.

최종 코드는 challenges Github repo에서 찾을 수 있습니다. 코드에 대한 조언이 있거나 다른 도전이 있을 경우 저에게 연락 주십시오😉 트위터에서 나는 네가 오늘 어떤 유용한 것을 배웠으면 좋겠어. 만약 네가 정말 배웠다면 다른 사람과 공유해 줘.
토트 킨스👋

Side Note: If you are an arabic speaker or understand arabic, you can also watch me coding that in an arabic tutorials in the following video on my technical arabic channel on Youtube

좋은 웹페이지 즐겨찾기