導言
近期實現一個需求,大概就是類似小紅書圖片輪播指示燈那樣,固定只顯示n個指示燈,若n個燈前方或者后方存在更多圖,則n個中最前方或者最后方的燈縮小展示。直接上圖:
【不會上傳視頻。。就湊合看下圖吧


產品表示:我要一模一樣的,也是五個燈,切換圖片時,指示燈自動滾動,要讓選中的居中,前方或者后方有更多圖,最前或者最后的燈要縮小顯示。
實現效果

效果1

效果2

效果3
構思方案
看了小紅書的實際效果后,個人認為實現方案大概是:全部的燈都渲染出來,但是只留出五個燈的顯示寬度,其他的overflow: hidden掉;再根據選中燈的位置,js控制橫向滾動,將選中燈滾動到視區中間;至於縮小的燈,則需要根據每個燈的index去判斷是否縮小顯示。但是具體哪些燈要縮小顯示呢,感覺是一個比較復雜的條件,一旦搞不好可能寫完了自己在看也看不明白了,決定先去網上找找參考方案。
參考方案
https://blog.csdn.net/qq_44656685/article/details/115376854
思路大概是根據總數量和選中燈的index,按照上面的是實現效果一樣,分幾個條件,不同條件渲染不同的燈和小燈,但是存在一個問題:這是一個純靜態的,沒有切換過渡的效果,特別在圖數量較多時,處於效果2的條件就會一直是純靜態的,看起來很奇怪。
綜合考慮后,決定按照構思方案去實現,不過參考方案也給了一定的啟發,那就是哪些燈縮小顯示的條件,這位好人直接給出來了,稍微改改就可以用了。
總結如下:
果然比較復雜。。。哈哈哈哈
實現方案
⬆️先放一個鏈接在這里
核心邏輯:
使選中的點滾動至視區中間
搭配css,dotWrapper這個樣式,就是為了控制視區寬度(為5個點+4個間隔的距離),在通過js強制控制scrollLeft使選中點定位到視區中間,window.requestAnimationFrame創造滾動的動畫效果
handleScrollDotView() { setTimeout(() => { const selected = document.querySelector('.selectedDot'); const selectedLeft = selected.getBoundingClientRect().x; // 將選中的點偏移至中間 const scrollDom = document.querySelector('.dotWrapper'); const offset = selectedLeft - (window.innerWidth - 8) / 2; const duration = 1000; const frames = Math.round(duration / 1000 * 16); let frame = 0; // 過渡幀數 const animate = () => { scrollDom.scrollLeft += offset / frames; if (++frame < frames) { window.requestAnimationFrame(animate); } }; window.requestAnimationFrame(animate); }, 100); }
點縮放的條件:【懶得搞格式了
<div className="dotWrapper"> { new Array(this.state.total).fill({}).map((_, index) => { return <div className={ `dot ${index === this.state.selectedIndex && 'selectedDot'} ${this.state.total > 5 && ( (this.state.selectedIndex < 3 && index >= 4) || (this.state.selectedIndex >= 3 && this.state.selectedIndex < this.state.total - 3 && Math.abs(index - this.state.selectedIndex) >= 2) || (this.state.selectedIndex >= this.state.total - 3 && index <= this.state.total - 5) ) && 'smallDot'}`} key={index} />; }) } </div>
