前言:之前寫過圖片切換組件,例如通過改變state,讀取圖片數組下標來實現切換,感覺效果不是很好,太過生硬,並且因為每次切換時候讀取到的下標時候會去重新請求圖片的url,重復浪費資源。
重新整理功能:
1、點擊右側icon時候切換下面4張圖片,並附帶有平移動畫效果
2、點擊左側icon切換前張圖片,並附帶有平移動畫效果
思路整理:
1、使用css的transform,可以將元素旋轉,縮放,移動,傾斜
2、使用object-fit:cover需要設置圖片填充效果,(每張圖片大小不一致)
3、保證每張圖片在同一行
4、切換時候設置transform的translateX偏移寬度
按照上面的思路我們貼下代碼和初步的實現:
初步less文件----------------
.wrap_scrollImg { width: 100%; height: 300px; background-color: #2C9806; overflow: hidden; position: relative; span { z-index: 11; position: absolute; display: inline-block; height: 50px; width: 50px; background-color: red; top: 0; bottom: 0; margin: auto; } .left_icon { left: 0; } .right_icon { right: 0; } ul { z-index: 10; height: 300px; white-space: nowrap; position: absolute; li { height: 100%; display: inline-block; width: 24%; margin-left: 1%; img { width: 100%; height: 100%; object-fit: cover; } } } }
初步jsx文件---------------
import React, { Component, useState, memo } from 'react'; import styles from './index.less'; function Index(props) { const { imgData } = props; const [translateX, setTranslateX] = useState(0); //設置偏移數值 const clickRightIcon = () => { setTranslateX(translateX + 400); //隨便寫個偏移值測試 }; const clickLeftIcon = () => { if (translateX === 0) return; setTranslateX(translateX - 400); }; console.log('translateX', translateX); return ( <div className={styles.wrap_scrollImg}> <span className={styles.left_icon} onClick={clickLeftIcon}></span> <span className={styles.right_icon} onClick={clickRightIcon}></span> <ul style={{ transform: `translateX(${translateX}px)` }}> {imgData.map(item => { return <li> <img src={item.imgUrl} alt={item.name}/> </li>; })} </ul> </div> ); } export default memo(Index);
以上代碼初步效果-------------
可以看到點擊左右方塊圖片‘切換了’,分析下有什么不足:每次點擊切換時候需要偏移的寬度不准確、左側邊緣有縫隙(margin-left導致的)、切換時候偏移效果生硬、左右切換方向錯了、偏移到最后一張圖片位置時候需要停止,
經過改造效果:
最終代碼:
less文件-----------------
.wrap_scrollImg { width: 100%; height: 220px; //background-color: #2C9806; overflow: hidden; position: relative; &:hover { span { display: inline-block; } } span { cursor: pointer; z-index: 11; position: absolute; display: none; background-color: rgba(0, 0, 0, 0.3); top: 0; bottom: 0; margin: auto; height: 35px; line-height: 35px; width: 24px; text-align: center; color: white; font-size: 20px; transition: 0.2s; &:hover { font-size: 22px; } } .left_icon { left: 0; } .right_icon { right: 0; } ul { z-index: 10; height: inherit; white-space: nowrap; position: absolute; transition: all 0.5s ease-in 0s; //偏移的過度效果 margin-right: -1%; //設置ul偏右-用來抵消li元素右邊距1%導致的缺口 li { height: 100%; display: inline-block; min-width: calc(24%); width: calc(24%); margin-right: 1%; //圖片右邊距 overflow: hidden; border-radius: 6px; cursor: pointer; img { transition: all 0.3s; width: 100%; height: 100%; object-fit: cover; &:hover { transform: scale(1.1); } } } } }
js文件---------------
import React, { Component, useState, memo, createRef } from 'react'; import styles from './index.less'; import { Icon } from 'antd'; function Index(props) { const ref = createRef(); const { imgData } = props; const [translateX, setTranslateX] = useState(0); //每次偏移數值 /** * 點擊右側按鈕 */ const clickRightIcon = () => { if (ref.current.scrollWidth < Math.abs(translateX) + Math.abs(ref.current.offsetWidth)) {//到最后一頁時候需要停止點擊按鈕 return; } setTranslateX(translateX - ref.current.offsetWidth); //每次滾動可見區域寬度 }; /** * 點擊左側按鈕 */ const clickLeftIcon = () => { if (translateX === 0) return; setTranslateX(translateX + ref.current.offsetWidth); }; console.log('translateX', translateX); console.log('ref', ref); return ( <div className={styles.wrap_scrollImg}> <span className={styles.left_icon} onClick={clickLeftIcon}><Icon type="left"/></span> <span className={styles.right_icon} onClick={clickRightIcon}><Icon type="right"/></span> <ul style={{ transform: `translateX(${translateX}px)` }} ref={ref}> {imgData.map(item => { return <li> <img src={item.imgUrl} alt={item.name}/> </li>; })} </ul> </div> ); } export default memo(Index);
以上因為沒有其他特定業務需求,所以就只封裝成這個樣子,有業務需求其實再在基礎上增加幾個參數就可以,例如每次圖片顯示多少張、或者切換過度時間為多少。思路對了就很簡單。需要比較注意的點我已經再上面給出注釋了