>웹 프론트엔드 >프런트엔드 Q&A >캐러셀 차트의 높이 조정 방법에 대한 자세한 예

캐러셀 차트의 높이 조정 방법에 대한 자세한 예

藏色散人
藏色散人앞으로
2023-04-01 08:30:022050검색
이 글은 캐러셀에 대한 적응형 높이를 만드는 방법을 주로 소개합니다. 관심 있는 친구들은 아래를 참고해 보세요.

이런 필요성이 발생했거나 비슷한 효과를 본 적이 있는지 모르겠습니다. 즉, 목록에 들어가서 캐러셀 이미지를 자세히 보면 손가락으로 캐러셀 이미지를 스크롤할 때 캐러셀의 높이 컨테이너가 조정됩니다. , 다음 내용을 위로 밀어 올리면 슬라이딩 프로세스 중에 높이가 계산되고, 놓을 때 다음 그림으로 스크롤됩니다. 해당 그림의 높이도 계산한 다음 느린 애니메이션 효과를 만듭니다. 아래 그림과 같습니다.

캐러셀 차트의 높이 조정 방법에 대한 자세한 예

위의 이미지 내용과 텍스트를 보면 알 수 있는데, 캐러셀이 슬라이드되면서 캐러셀의 높이도 달라집니다. 더 이상 고민하지 않고 바로 코드로 넘어가겠습니다.

구현 방법

마우스 마우스 또는 손가락 슬라이딩 터치 이벤트를 듣고 그림을 제어할 수 있습니다. 여기서는 ​​의 아이디어에 대해서만 설명합니다. 캐러셀 기능 구현의 핵심은 높은 적응성을 달성하는 방법입니다. mounse 或者手指的滑动 touch 事件来控制图片,这里本文只说一下轮播的功能实现思路,重点说的是怎么实现高度的自适应。

直接开始正文,先看 html 代码结构。

html 结构

<div>
  <div>
    <div>
      <div>
        <img  alt="캐러셀 차트의 높이 조정 방법에 대한 자세한 예" >
      </div>
      <div>
        <img  alt="캐러셀 차트의 높이 조정 방법에 대한 자세한 예" >
      </div>
      <div>
        <img  alt="캐러셀 차트의 높이 조정 방법에 대한 자세한 예" >
      </div>
    </div>
  </div>
  <div>这是一段内容</div>
</div>

css 样式

.container {
  width: 100%;
  overflow: hidden;
}.wrapper {
  width: 100%;
}.swiper {
  font-size: 0;
  white-space: nowrap;
}.item {
  display: inline-block;
  width: 100%;
  vertical-align: top; // 一定要使用顶部对齐,不然会出现错位的情况
}.item img {
  width: 100%;
  height: auto;
  display: block;
}.content {
  position: relative;
  z-index: 9;
  font-size: 14px;
  text-align: center;
  padding-top: 20px;
  background-color: #fff;
  height: 200px;
}

值得注意的地方有几点;

  1. 在使用父级 white-space 时,子集元素设置 display: inline-block 会出现高度不同的排列错位,解决办法就是加上一句 vertical-align: top ,具体什么原因我也不细讲了。
  2. 另外父级还要设置 font-size: 0 ,如果没加上的话,就会出现两个子集有空隙出现,加上之后空隙就会去掉。
  3. img 图片最好设置成高度自适应,宽度100% 还要加上 display: block ,没有的话底部就会出现间隙。

写好上面的 html容器部分和 样式,下面就看一下 js 上是怎么处理的。

Js 实现

开始之前我们先思考一下去怎么实现这个轮播以及高度的自适应问题,分为几步操作;

  1. 鼠标按下时,需要记录当前的位置和一些其他初始化的信息,并且给当前的父元素添加相应的鼠标事件。
  2. 鼠标移动时,需要通过当前实时移动时点位和按下时点位的相减,得到移动的距离位置,然后再赋值给父元素设置其样式 transform 位置,中间还做其他的边界处理,当然还有高度的变化。
  3. 鼠标释放是,通过移动时记录的距离信息判断是左滑还是右滑,拿到其对应的索引,通过索引就可以计算到滚动下一张的距离,释放之后设置 transition 过渡动画即可。

按照我们试想的思路,开始正文;

初始化数据

const data = {
  ele: null,
  width: 0,
  len: 0,
  proportion: .3,
  type: false,
  heights: [500, 250, 375],
  currentIndex: 0,
  startOffset: 0,
  clientX: 0,
  distanceX: 0,
  duration: 30,
  touching: false
}

const wrapper = data.ele = document.querySelector(&#39;.wrapper&#39;)
const items = document.querySelectorAll(&#39;.item&#39;)
data.width = wrapper.offsetWidth
data.len = items.length - 1
wrapper.addEventListener(&#39;touchstart&#39;, onStart)
wrapper.addEventListener(&#39;mousedown&#39;, onStart)

注意,这里在做高度之前,我们需要等图片加载完成之后才能拿到每一个元素的高度,我这里为了省懒就没写具体代码,上面的 heights 对应的是每个图片在渲染之后的高度,一般情况下最好让后端传回来带宽高,这样就不需要用 onload 再去处理这个。

鼠标按下时

function onStart(event) {
  if (event.type === 'mousedown' && event.which !== 1) return
  if (event.type === 'touchstart' && event.touches.length > 1) return
  data.type = event.type === 'touchstart'
  const events = data.type ? event.touches[0] || event : event

  data.touching = true
  data.clientX = events.clientX
  data.startOffset = data.currentIndex * -data.width

  data.ele.style.transition = `none`
  window.addEventListener(data.type ? 'touchmove' : 'mousemove', onMove, { passive: false })
  window.addEventListener(data.type ? 'touchend' : 'mouseup', onEnd, false)
}

上面的代码里面我做了PC和移动端的兼容,跟计划的一样,保存一下 clientX 坐标和一个初始的坐标 startOffset 这个由当前索引和父级宽度计算得到,场景是当从第二张图片滚动到第三张图片时,会把之前的第一张图片的距离也要加上去,不然就计算错误,看下面滑动时的代码。

另外在做监听移动的时候加上了 passive: false 是为了在移动端兼容处理。

鼠标移动时

function onMove(event) {
  event.preventDefault()
  if (!data.touching) return
  const events = data.type ? event.touches[0] || event : event

  data.distanceX = events.clientX - data.clientX

  let translatex = data.startOffset + data.distanceX
  if (translatex > 0) {
    translatex = translatex > 30 ? 30 : translatex
  } else {
    const d = -(data.len * data.width + 30)
    translatex = translatex <p>做了一个边界处理的,超了 30 的距离就不让继续滑动了,加上之前保存的 <code>startOffset</code> 的值,得到的就是具体移动的距离了。</p><h4 data-id="heading-7">鼠标释放时</h4><pre class="brush:php;toolbar:false">function onEnd() {
  if (!data.touching) return
  data.touching = false

  // 通过计算 proportion 滑动的阈值拿到释放后的索引
  if (Math.abs(data.distanceX) > data.width * data.proportion) {
    data.currentIndex -= data.distanceX / Math.abs(data.distanceX)
  }
  if (data.currentIndex  data.len) {
    data.currentIndex = data.len
  }
  const translatex = data.currentIndex * -data.width

  data.ele.style.transition = 'all .3s ease'
  data.ele.style.transform = `translate3d(${translatex}px, 0, 0)`
  data.ele.style.webkitTransform = `translate3d(${translatex}px, 0, 0)`

  window.removeEventListener(data.type ? 'touchmove' : 'mousemove', onMove, { passive: false })
  window.removeEventListener(data.type ? 'touchend' : 'mouseup', onEnd, false)
}

通过计算 proportion 滑动的阈值拿到释放后的索引,也就是超过父级宽度的三分之一时释放就会滚动到下一张,拿到索引之后就可以设置需要移动的最终距离,记得加上 transition 做一个缓动效果,最后也别忘记移除事件的监听。

至此上面的简单的轮播效果就大功告成了,但是还缺少一点东西,就是本篇需要讲的自适应高度,为了方便理解就单独拿出来说一下。

高度自适应

在移动时就可以在里面做相关的代码整理了, onMove

텍스트를 직접 시작하고 먼저 html 코드 구조를 살펴보겠습니다. 🎜🎜🎜html 구조🎜🎜
const index = data.currentIndex
const currentHeight = data.heights[index]
    
// 判断手指滑动的方向拿到下一张图片的高度
let nextHeight = data.distanceX > 0 ? data.heights[index - 1] : data.heights[index + 1]
let diffHeight = Math.abs((nextHeight - currentHeight) * (data.distanceX / data.width))
let realHeight = currentHeight + (nextHeight - currentHeight > 0 ? diffHeight : -diffHeight) 
 data.ele.style.height = `${realHeight}px`
🎜🎜css 스타일🎜🎜
// ... 因为上面已经拿到了下一张的索引 currentIndex
const currentHeight = data.heights[data.currentIndex]

data.ele.style.height = `${currentHeight}px`
🎜몇 가지 주목할 만한 점이 있습니다.🎜
  1. 상위 공백을 사용할 때 하위 집합 요소는 display: inline-block은 높이가 다를 때 정렬 오류를 발생시킵니다. 해결책은 vertical-align: top을 추가하는 것입니다. 구체적인 이유에 대해서는 자세히 설명하지 않겠습니다.
  2. 또한 상위 항목도 font-size: 0으로 설정해야 합니다. 추가하지 않으면 추가한 후 두 하위 집합 사이에 간격이 생깁니다. 제거됩니다.
  3. img 이미지를 높이 적응형으로 설정하고 100%display: block을 추가하는 것이 가장 좋습니다. 바닥에 틈이 생기세요.
🎜위의 html 컨테이너 부분과 스타일을 작성한 후 js가 어떻게 처리되는지 살펴보겠습니다. 🎜🎜🎜J 구현🎜🎜🎜시작하기 전에 먼저 여러 단계로 나누어진 캐러셀 및 높이 적응 문제를 구현하는 방법에 대해 생각해 보겠습니다. 🎜
  1. 마우스를 누르면 현재 위치가 필요합니다. 기록할 내용과 기타 초기화 정보를 저장하고 해당 마우스 이벤트를 현재 상위 요소에 추가합니다.
  2. 마우스가 움직일 때 현재 실시간 🎜이동할 때의 지점과 🎜눌렀을 때의 지점을 빼서 이동 거리와 위치를 구한 다음 이를 상위 요소에 할당하여 스타일 transform 위치를 설정하면 다른 경계 처리도 중간에 수행되며 물론 높이도 변경됩니다.
  3. 마우스를 놓으면 이동 중에 기록된 거리 정보를 사용하여 왼쪽 또는 오른쪽으로 슬라이딩하는지 확인하고 해당 인덱스를 구하여 다음 페이지를 스크롤할 수 있는 거리를 계산할 수 있습니다. 인덱스이며 릴리스transition 후에 설정됩니다. 전환 애니메이션이면 충분합니다.
🎜우리가 상상한 아이디어에 따라 텍스트를 시작합니다. 🎜

초기화 데이터

rrreee🎜높이를 수행하기 전에 기다려야 합니다. 여기서 각 요소의 높이는 이미지가 로드된 후에만 얻을 수 있습니다. 게으름을 피하기 위해 여기에 특정 코드를 작성하지 않았습니다. 위의 높이는 렌더링 후 각 이미지의 높이에 해당합니다. 일반적으로 이것이 가장 좋습니다. 이렇게 하면 백엔드가 높은 대역폭을 반환할 수 있으므로 이를 처리하기 위해 onload를 사용할 필요가 없습니다. 🎜

마우스를 눌렀을 때

rrreee🎜위 코드에서는 예정대로 clientX를 저장하여 PC와 모바일 단말기에 호환되게 만들었습니다. code > 좌표 및 초기 좌표 <code>startOffset 이는 현재 인덱스와 상위 너비에서 계산됩니다. 시나리오에서는 두 번째 사진에서 세 번째 사진으로 스크롤할 때 이전 첫 번째 사진의 거리가 같아야 합니다. 그렇지 않으면 계산이 잘못됩니다. 아래 슬라이딩 코드를 참조하세요. 🎜🎜또한, 모바일 측 호환성을 위해 움직임 모니터링 시 passive: false가 추가됩니다. 🎜

마우스가 움직일 때

rrreee🎜는 경계 처리를 완료했으며 30 거리와 이전에 저장된 startOffset을 넘어서는 더 이상의 슬라이딩을 허용하지 않습니다. 얻은 값은 이동한 특정 거리입니다. 🎜

마우스를 놓았을 때

rrreee🎜비율 슬라이딩 임계값을 계산하여 마우스를 놓은 후의 인덱스를 얻습니다. 이는 3배 더 많은 수치입니다. 놓으면 다음 항목으로 스크롤됩니다. 색인을 얻은 후 이동할 최종 거리를 설정할 수 있습니다. 여유 효과를 생성하려면 전환을 추가하세요. 모니터링이 끝나면 이벤트를 제거하는 것을 잊지 마세요. 🎜🎜이제 위의 간단한 캐러셀 효과는 완성되었지만 아직 한 가지 빠진 것이 있는데, 바로 이 글에서 다루어야 할 적응형 높이에 대한 이해를 돕기 위해 별도로 이야기하겠습니다. 🎜🎜🎜높이 적응🎜🎜🎜이동 시 해당 코드를 정리하여 실시간 높이를 얻을 수 있는 onMove 함수에 다음 코드를 추가하세요. 🎜
const index = data.currentIndex
const currentHeight = data.heights[index]
    
// 判断手指滑动的方向拿到下一张图片的高度
let nextHeight = data.distanceX > 0 ? data.heights[index - 1] : data.heights[index + 1]
let diffHeight = Math.abs((nextHeight - currentHeight) * (data.distanceX / data.width))
let realHeight = currentHeight + (nextHeight - currentHeight > 0 ? diffHeight : -diffHeight) 
 data.ele.style.height = `${realHeight}px`

这里是移动时的高度变化,另外还需要在释放时也要处理, onEnd 函数里加上以下代码。

// ... 因为上面已经拿到了下一张的索引 currentIndex
const currentHeight = data.heights[data.currentIndex]

data.ele.style.height = `${currentHeight}px`

因为上面已经拿到了下一张的索引 currentIndex 所以再滚动到下一张是就直接通过数据获取就可以了。

推荐学习:《web前端开发视频教程

위 내용은 캐러셀 차트의 높이 조정 방법에 대한 자세한 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제