I don’t know if you have encountered such a need or seen a similar effect. When you enter the list and view the carousel image in detail, the height container of the carousel will adapt when your finger scrolls the carousel image, so as follows The content will be squeezed upward, the height will be calculated during the sliding process, and it will scroll to the next picture when released. It will also calculate the height of the corresponding picture, and then create a slow animation effect. Just like the picture below.
#You can see the image content and text above, and the height changes as the carousel slides. Without further ado, let’s get straight to the code.
Implementation method
You can control the picture by listening to the mouse mounse
or finger sliding touch
event. This article only Let’s talk about the idea of implementing the carousel function, focusing on how to achieve a high degree of adaptability.
Let’s start the text directly and look at the html code structure first.
html structure
<div> <div> <div> <div> <img alt="Detailed example of how to adjust the height of the carousel chart" > </div> <div> <img alt="Detailed example of how to adjust the height of the carousel chart" > </div> <div> <img alt="Detailed example of how to adjust the height of the carousel chart" > </div> </div> </div> <div>这是一段内容</div> </div>
css style
.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; }
There are several points worth noting;
white-space
, the subset element setting display: inline-block
will cause misalignment with different heights. The solution is to add a vertical-align: top
, I won’t go into details about the specific reasons. font-size: 0
. If it is not added, there will be a gap between the two subsets. After adding it, the gap will be removed. 100%
and add display: block
, otherwise there will be a gap at the bottom. After writing the above html
container part and style, let’s take a look at how js
is processed.
Js implementation
Before we start, let’s first think about how to implement this carousel and highly adaptive problem, which is divided into several steps;
transform
position, and also performs other border processing in the middle, and of course changes in height. transition
Just transition animation. According to the idea we imagined, start the text;
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)
Note that before doing the height here, we need to wait for the image to be loaded before we can get it To the height of each element, I didn’t write specific code here to save myself from laziness. The above heights
corresponds to the height of each image after rendering. Generally, it is best to let the backend pass back the bandwidth. High, so there is no need to use onload
to handle this.
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) }
In the above code, I have made it compatible with PC and mobile terminals. As planned, save the clientX
coordinates and an initial coordinate. startOffset
This is calculated from the current index and parent width. The scenario is that when scrolling from the second picture to the third picture, the distance from the previous first picture will also be added, otherwise Regarding the calculation error, look at the code when sliding below.
In addition, passive: false
is added when monitoring movement for the purpose of compatibility on the mobile side.
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)` }
is processed with a boundary. If the distance exceeds 30, it will not be allowed to continue sliding. Adding the previously saved value of startOffset
, What you get is the specific distance moved.
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) }
By calculating the sliding threshold, the index after release is obtained, that is, it will be released when it exceeds one-third of the parent width. Scroll to the next picture. After getting the index, you can set the final distance to move. Remember to add transition
to create a easing effect. Finally, don’t forget to remove the event listener. At this point, the simple carousel effect above is complete, but there is still one thing missing, which is the adaptive height that this article needs to talk about. To facilitate understanding, I will talk about it separately.
You can organize the relevant code in it when moving. Add the following code to the
onMove function to obtain Real time height. <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">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`</pre><div class="contentsignin">Copy after login</div></div><p>这里是移动时的高度变化,另外还需要在释放时也要处理, <code>onEnd
函数里加上以下代码。
// ... 因为上面已经拿到了下一张的索引 currentIndex const currentHeight = data.heights[data.currentIndex] data.ele.style.height = `${currentHeight}px`
因为上面已经拿到了下一张的索引 currentIndex
所以再滚动到下一张是就直接通过数据获取就可以了。
The above is the detailed content of Detailed example of how to adjust the height of the carousel chart. For more information, please follow other related articles on the PHP Chinese website!