이런 필요성이 발생했거나 비슷한 효과를 본 적이 있는지 모르겠습니다. 즉, 목록에 들어가서 캐러셀 이미지를 자세히 보면 손가락으로 캐러셀 이미지를 스크롤할 때 캐러셀의 높이 컨테이너가 조정됩니다. , 다음 내용을 위로 밀어 올리면 슬라이딩 프로세스 중에 높이가 계산되고, 놓을 때 다음 그림으로 스크롤됩니다. 해당 그림의 높이도 계산한 다음 느린 애니메이션 효과를 만듭니다. 아래 그림과 같습니다.
위의 이미지 내용과 텍스트를 보면 알 수 있는데, 캐러셀이 슬라이드되면서 캐러셀의 높이도 달라집니다. 더 이상 고민하지 않고 바로 코드로 넘어가겠습니다.
구현 방법
마우스 마우스
또는 손가락 슬라이딩 터치
이벤트를 듣고 그림을 제어할 수 있습니다. 여기서는 의 아이디어에 대해서만 설명합니다. 캐러셀 기능 구현의 핵심은 높은 적응성을 달성하는 방법입니다. 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; }
值得注意的地方有几点;
white-space
时,子集元素设置 display: inline-block
会出现高度不同的排列错位,解决办法就是加上一句 vertical-align: top
,具体什么原因我也不细讲了。font-size: 0
,如果没加上的话,就会出现两个子集有空隙出现,加上之后空隙就会去掉。100%
还要加上 display: block
,没有的话底部就会出现间隙。写好上面的 html
容器部分和 样式,下面就看一下 js
上是怎么处理的。
Js 实现
开始之前我们先思考一下去怎么实现这个轮播以及高度的自适应问题,分为几步操作;
transform
位置,中间还做其他的边界处理,当然还有高度的变化。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('.wrapper') const items = document.querySelectorAll('.item') data.width = wrapper.offsetWidth data.len = items.length - 1 wrapper.addEventListener('touchstart', onStart) wrapper.addEventListener('mousedown', 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 < d ? d : translatex } data.ele.style.transform = `translate3d(${translatex}px, 0, 0)` data.ele.style.webkitTransform = `translate3d(${translatex}px, 0, 0)` }
做了一个边界处理的,超了 30 的距离就不让继续滑动了,加上之前保存的 startOffset
的值,得到的就是具体移动的距离了。
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 < 0) { data.currentIndex = 0 } else 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
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`
// ... 因为上面已经拿到了下一张的索引 currentIndex const currentHeight = data.heights[data.currentIndex] data.ele.style.height = `${currentHeight}px`
공백
을 사용할 때 하위 집합 요소는 < code>display: inline-block은 높이가 다를 때 정렬 오류를 발생시킵니다. 해결책은 vertical-align: top
을 추가하는 것입니다. 구체적인 이유에 대해서는 자세히 설명하지 않겠습니다. font-size: 0
으로 설정해야 합니다. 추가하지 않으면 추가한 후 두 하위 집합 사이에 간격이 생깁니다. 제거됩니다. 100%
및 display: block
을 추가하는 것이 가장 좋습니다. 바닥에 틈이 생기세요. html
컨테이너 부분과 스타일을 작성한 후 js
가 어떻게 처리되는지 살펴보겠습니다. 🎜🎜🎜J 구현🎜🎜🎜시작하기 전에 먼저 여러 단계로 나누어진 캐러셀 및 높이 적응 문제를 구현하는 방법에 대해 생각해 보겠습니다. 🎜transform
위치를 설정하면 다른 경계 처리도 중간에 수행되며 물론 높이도 변경됩니다. transition
후에 설정됩니다. 전환 애니메이션이면 충분합니다. 높이
는 렌더링 후 각 이미지의 높이에 해당합니다. 일반적으로 이것이 가장 좋습니다. 이렇게 하면 백엔드가 높은 대역폭을 반환할 수 있으므로 이를 처리하기 위해 onload
를 사용할 필요가 없습니다. 🎜clientX</를 저장하여 PC와 모바일 단말기에 호환되게 만들었습니다. code > 좌표 및 초기 좌표 <code>startOffset
이는 현재 인덱스와 상위 너비에서 계산됩니다. 시나리오에서는 두 번째 사진에서 세 번째 사진으로 스크롤할 때 이전 첫 번째 사진의 거리가 같아야 합니다. 그렇지 않으면 계산이 잘못됩니다. 아래 슬라이딩 코드를 참조하세요. 🎜🎜또한, 모바일 측 호환성을 위해 움직임 모니터링 시 passive: false
가 추가됩니다. 🎜startOffset을 넘어서는 더 이상의 슬라이딩을 허용하지 않습니다.
얻은 값은 이동한 특정 거리입니다. 🎜비율
슬라이딩 임계값을 계산하여 마우스를 놓은 후의 인덱스를 얻습니다. 이는 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
所以再滚动到下一张是就直接通过数据获取就可以了。
위 내용은 캐러셀 차트의 높이 조정 방법에 대한 자세한 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!