애니메이션 슬라이더 만들기 - WotW

31183 단어 vuewotwwebdevtutorial
이번 주 작은 위젯 시리즈에 오신 것을 환영합니다. 이곳에서 저는 아주 좋은 UI/UX 구성 요소의 GIF나 동영상을 얻고 코드로 그것을 생활 속으로 가져왔습니다.
이번에는 모든 일에 사용할 수 있지만 온도 슬라이더를 만들 것입니다.
submission에서 영감을 얻은 ramykhuffash은 다음과 같다.

준비 작업


오늘날의 작은 부품에 대해 우리는 Vue.js을 사용하고 일부 애니메이션에 대해서는 TweenMax을 사용할 것이다.우리는 온도 아이콘이 하나 더 필요하기 때문에 Font Awesome 중 하나를 사용할 것이다.
만약 네가 계속하고 싶다면, 너는 이 codepen template을 갈라놓을 수 있다. 그것은 이미 의존 관계가 있다.

설계와 일치


이 작은 위젯의 HTML 표시는 통상보다 좀 복잡하기 때문에 이번에는 HTML+CSS를 사용하여 원본 디자인과 일치할 때까지 여러 부분으로 분해할 것입니다.
위아래 설정을 시작으로 위쪽은 숫자, 아래쪽은 슬라이더 컨트롤을 포함합니다.
<div id="app" class="main-container">
  <div class="upper-container">

  </div>
  <div class="lower-container">

  </div>
</div>
스타일을 설정하기 전에 body의 몇 가지 주요 CSS 속성이 필요합니다.
body {
  margin: 0;
  color: white;
  font-family: Arial, Helvetica, sans-serif;
}
우리는 0 주위에 간격이 생기지 않도록 여백을 main-container으로 설정합니다.colorfont-family도 우리 요소에서 중복되지 않도록 설정합니다.
현재 우리는 CSS grid 속성을 사용하여 화면을 두 부분으로 나눌 것입니다. 위의 부분은 수직 높이의 3/4을 취해야 합니다. fr을 사용하여 이 점을 실현할 수 있습니다.
.main-container {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 3fr 1fr;
  height: 100vh;
  overflow-x: hidden;
}
100vh 속성의 height 값을 주의하십시오. 우리의div가 전혀 내용이 없어도 화면을 수직으로 채울 수 있습니다.
또한 요소가 작은 화면에서 경계를 넘으면 overflow-x: hidden 속성이 작은 위젯에 스크롤 막대를 표시하지 못하게 합니다.
이제 각 부분에 배경색만 추가하면 됩니다.위쪽의 경우 사다리를 사용합니다.
.upper-container {
  position: relative;
  background: linear-gradient(to bottom right, #5564C2, #3A2E8D);
}
.lower-container {
  background-color: #12132C;
}
position: relative에 설정된 upper-container 속성은 내부 요소를 찾을 때 사용됩니다.

우리는 방금 몸을 풀기 시작했다.
위 부분의 숫자는 논리에 맞는 다음 단계인 것 같다.
  <!-- inside .upper-container -->
    <h2 class="temperature-text">10</h2>
이것은 현재 온도를 표시하는 큰 숫자로 CSS를 사용하여 위치를 더 잘 정할 수 있습니다.
.temperature-text {
  position: absolute;
  bottom: 150px;
  font-size: 100px;
  width: 100%;
  text-align: center;
  user-select: none;
}
user-select: none 속성은 슬라이더와 상호작용할 때 텍스트를 선택하지 않도록 도와줄 수 있습니다.
다음 숫자를 추가하기 전에 일부 데이터로 Vue 인스턴스를 시작하여 불필요한 태그 요소를 반복하지 않도록 합니다.
new Vue({
  el: '#app',
  data: {
    temperatureGrades: [10, 15, 20, 25, 30]
  }
})
현재 우리는 temperatureGrades 수조를 사용하여 디자인의 이러한 요소를 표시할 수 있다.
    <!-- just after .temperature-text -->
    <div class="temperature-graduation">
      <div class="temperature-element" 
           v-for="el in temperatureGrades" 
           :key="el">
        <span class="temperature-element-number">{{el}}</span><br>
        <span class="temperature-element-line">|</span>
      </div>
    </div>
각 숫자에 | 문자를 렌더링하고 있으므로 스타일을 눈금자로 설정할 수 있습니다.
중국어 텍스트의 숫자와 줄을 선택해야 하는 경우, 우리는 temperature-element 규칙 내에서 이렇게 할 것이다.우리는 또한 원소를 inline-blocks으로 하여 서로 인접할 수 있도록 할 것이다.마지막으로 | 문자는 더 작아야 하며, font-size은 다음과 같은 책임을 집니다.
.temperature-element {
  text-align: center;
  display: inline-block;
  width: 40px;
  margin: 0 10px 0 10px;
  opacity: 0.7;
}
.temperature-element-line {
  font-size: 7px;
}
.temperature-graduation 요소를 검사하면 그 폭이 300px인 것을 볼 수 있습니다. 그 폭을 가운데에 두기 위해 우리는 다음과 같은 방식으로 계산 값을 사용할 수 있습니다.
.temperature-graduation {
  position: absolute;
  left: calc(50% - 150px); // subtracting half the width to center
  bottom: 25px;
  user-select: none;
}
또한 bottom 속성을 설정하여 낮은 부분의 바로 위에 표시합니다.

슬라이더


상반부는 이미 준비가 되었으니, 지금 우리는 슬라이더 컨트롤을 추가할 것이다.버튼은 간단합니다. 아이콘이 있는 div만 있으면 됩니다.
  <!-- inside .lower-container -->
    <div class="slider-container">
      <div class="slider-button">
        <i class="fas fa-thermometer-empty slider-icon"></i>
      </div>
    </div>
이제 다음 대부분의 CSS 코드는 요소를 원하는 위치에 배치할 수 있도록 수동으로 조정된 값으로 버튼의 스타일을 설계합니다.
.slider-container {
  width: 150px;
  height: 80px;
  margin-top: -30px;
  margin-left: calc(50% - 187px);
  position: relative;
}
.slider-button {
  position: absolute;
  left: 42px;
  top: 5px;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: #2724A2;

  cursor: grab;
  cursor: -webkit-grab; 
  cursor: -moz-grab;
}

.slider-icon {
  margin-top: 16px;  
  margin-left: 21px;  
  color: white;
}
커서가 멈추면 버튼의 grab 값이 커서를 손으로 변환합니다.
슬라이더는 현재'파도'와 유사한 모양만 부족합니다. 처음에 border-radius 값을 사용하고 div 값을 회전하려고 했지만 안타깝게도 디자인과 일치하지 않습니다.내가 마지막으로 한 것은 SVG의 도형이다. 보기에 이렇다.

모양 코드는 다음과 같습니다.
    <!-- inside .slider-container -->
      <svg width="150" height="30" viewBox="0 0 150 30" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M74.3132 0C47.0043 2.44032e-05 50.175 30 7.9179 30H144.27C99.4571 30 101.622 -2.44032e-05 74.3132 0Z" transform="translate(-7.38794 0.5)" fill="#12132C"/>
      </svg>

이것은 좀 힘들지만, 우리는 이미 설계를 준비했다.

상호작용


지금까지 이 작은 위젯의 상호작용에서 가장 주의해야 할 것은 슬라이더를 끄는 것이다.우리는 이전에 할 때도 한 적이 있기 때문에 나는 비슷한 방법을 따를 것이다.
  // inside data
    dragging: false,
    initialMouseX: 0,
    sliderX: 0,
    initialSliderX: 0
이러한 데이터 속성은 사용자가 드래그, 마우스 및 슬라이더 위치를 언제 시작하거나 중지하는지 추적하는 데 도움을 줍니다.
사용자가 상호 작용할 때 다음 메서드는 이러한 변수를 초기화합니다.
  // after data
  methods: {
    startDrag (e) {
      this.dragging = true
      this.initialMouseX = e.pageX
      this.initialSliderX = this.sliderX
    },
    stopDrag () {
      this.dragging = false
    },
    mouseMoving (e) {
      if(this.dragging) {
        // TODO move the slider        
      }
    }
  }
이제 템플릿에 연결합시다
<div id="app" class="main-container"
    @mousemove="mouseMoving"
    @mouseUp="stopDrag">
      <!-- ... inside .slider-container
        <div class="slider-button" 
             @mouseDown="startDrag">

@mouseDown 동작은 슬라이더 단추에 설정되어 있지만 @mouseMove@mouseUp은 주div 단계에 있습니다.
이 뒤에 있는 이유는 사용자가 슬라이더 단추를 누르기 시작하지만, 커서를 이동할 때, 그들은 보통 슬라이더 궤적을 벗어난다. 만약 마우스를 단추 밖에 놓으면, 그것은 추적되지 않을 뿐만 아니라, 단추를 다시 클릭할 때까지 따라갈 것이다.
이제 mouseMoving 방법을 하나의 알고리즘으로 채우자. 이 알고리즘은 sliderX 속성을 필요한 위치에 설정한다.우리는 슬라이더를 위해 우리가 이전에 한 잣대와 일치하도록 제약을 설명해야 한다.
// before the Vue instance
const sliderMinX = 0
const sliderMaxX = 240

  // inside mouseMoving method
    // replace the "TODO" line with this:
    const dragAmount = e.pageX - this.initialMouseX
    const targetX = this.initialSliderX + dragAmount

    // keep slider inside limits
    this.sliderX = Math.max(Math.min(targetX, sliderMaxX), sliderMinX)

  // after methods
  computed: {
    sliderStyle () {
      return `transform: translate3d(${this.sliderX}px,0,0)`
    }
  }
계산 속성 sliderStyle 메모리 슬라이더의 위치를 알 수 있습니다. .slider-container에 연결하기만 하면 됩니다.
  <div class="slider-container" :style="sliderStyle">
우리는 거의 작업하는 슬라이더 컨트롤러가 있지만, 슬라이더 값을 추적하는 중요한 것이 부족하다.이것은 매우 복잡하게 들릴 수 있지만, 우리는 계산 속성을 사용하여 이 값을 계산할 수 있다. 왜냐하면 우리는 이미 sliderX의 위치를 알고 있기 때문이다.
  // inside computed    
    currentTemperature () {
      const tempRangeStart = 10
      const tempRange = 20 // from 10 - 30
      return (this.sliderX / sliderMaxX * tempRange ) + tempRangeStart
    }
.temperature-text 요소 내에서 렌더링하여 다음 작업을 수행할 수 있습니다.
  <h2 class="temperature-text">{{currentTemperature}}</h2>

문제는 부동 소수점을 렌더링하고 있다는 것입니다.우리는 필터를 통해 이런 상황을 피할 수 있다.
  // after data
  filters: {
    round (num) {
      return Math.round(num)
    }
  },
이제 우리는 이렇게 필터를 사용할 수 있다.
  <h2 class="temperature-text">{{currentTemperature | round}}</h2>

마무리 작업


우리는 여기까지 작은 부품을 이렇게 운행할 수 있지만, 그것은 여전히 세부 사항이 부족하다.
온도가 25도를 넘으면 배경은 색을 바꾸고 눈금자 숫자도 파도 모양으로 이동해야 한다.
백그라운드에서 우리는 위에서 몇 가지 상수와 새로운 데이터 속성을 설명할 것이다.
const coldGradient = {start: '#5564C2', end: '#3A2E8D'}
const hotGradient = {start:'#F0AE4B', end: '#9B4D1B'}

// inside Vue
    // inside data
      gradientStart: coldGradient.start,
      gradientEnd: coldGradient.end

    //inside computed
      bgStyle () {
        return `background: linear-gradient(to bottom right, ${this.gradientStart}, ${this.gradientEnd});`
      }
그래디언트 배경에 필요한 색상이 유지됩니다.bgStyle 계산 속성은 gradientStartgradientEnd이 변경될 때마다 배경을 생성합니다.해당 HTML 요소에 바인딩합니다.
  <div class="upper-container" :style="bgStyle">
지금은 똑같아 보이지만 mouseMoving 방법에 규칙을 추가하여 애니메이션을 설정하면 상황이 달라집니다.
    // set bg color
    let targetGradient = coldGradient
    if (this.currentTemperature >= 25) {
      targetGradient = hotGradient
    }

    if(this.gradientStart !== targetGradient.start) {
      // gradient changed
      TweenLite.to(this, 0.7, {
        'gradientStart': targetGradient.start,
        'gradientEnd': targetGradient.end
      }) 
    }
우리가 하고 있는 것은 온도가 25도 이상으로 변화할 때 사다리꼴 값을 냉각에서 열로 바꾸는 것이다.변환은 순수한 색상에만 적용되기 때문에 CSS 변환이 아닌 TweenLite로 이루어집니다.
마지막으로 슬라이더가 눈금자 요소에 가까우면 Y 위치를 변경해야 합니다.
    <div class="temperature-element" v-for="el in temperatureGrades"
           :style="tempElementStyle(el)"
           :key="el">
이전 절과 유사하게, 우리는 방법을 통해 변경할 스타일을 연결할 것입니다. 이 방법은 모든 눈금자의 값을 받아들일 것입니다.이제 몇 가지 수학 계산 거리를 만들고 CSS 변환 도구를 만들 수 있습니다.
  // inside methods
    tempElementStyle (tempNumber) {
      const nearDistance = 3
      const liftDistance = 12

      // lifts up the element when the current temperature is near it
      const diff = Math.abs(this.currentTemperature - tempNumber)
      const distY = (diff/nearDistance) - 1

      // constrain the distance so that the element doesn't go to the bottom
      const elementY = Math.min(distY*liftDistance, 0)
      return `transform: translate3d(0, ${elementY}px, 0)`
    }
이제 최종 결과!
이것이 바로 이번 주의 작은 부품이다.
자세한 내용을 보려면 다른 WotW를 참조하십시오.



  • 또한 다음 주 특정 위젯을 보려면 설명 섹션에 게시하십시오.

    좋은 웹페이지 즐겨찾기