前面寫了兩篇關於 slider 組件如何實現的文章,有興趣的朋友能夠點擊這裏 原生 slider 組件的實現 和 React slider組件的實現 查看,今天寫一篇關於 3D 輪播圖實現原理的文章。javascript
目前在找實習工做,有合適的機會但願小夥伴們多多推薦~css
本文最終的 3D 輪播效果以下圖:html
依然參照原來的思路,按照一個正規的項目來對待,咱們仍是按照以下過程來實現。react
由於咱們是要實現一個 3D 輪播組件,因此不可避免地要使用一些 3D 屬性,除了在 W3CSchool 上學習,我還買了本小冊 WebGL 入門與實踐,雖然這是本講解 Webgl 的小冊,可是這本小冊也開闢了幾個章節講述 CSS3 中 3D 屬性的用法,給我帶來了一些新的思路。webpack
列舉一下咱們的需求:css3
需求比較簡單,核心就是 3D 輪播效果。git
產品的需求到了,那麼做爲開發人員,要開始思考如何實現產品的需求了,除此以外,還須要考慮將來產品的意圖,按照這個思路,我又想到了一些配置項,前面也講過,這些都是隱含的開發需求:github
那麼咱們要開始寫設計方案了。web
實現主要就是利用 css3 transform 屬性的 translateY 和 translateZ 值,將四張圖片經過前移後移、上移、下移組成一個圖片方盒。 拿四張 300px 高的圖片舉例。
.container{
position: relative;
transform-style: preserve-3d;
}
複製代碼
.imgs:nth-child(1){
transform: translateZ(150px);
}
.imgs:nth-child(2){
transform: translateY(-150px) rotateX(90deg);
}
.imgs:nth-child(3){
transform: translateZ(-150px) rotateX(180deg);
}
.imgs:nth-child(4){
transform: translateY(150px) rotateX(270deg);
}
複製代碼
以上兩個簡單的設置,就能夠造成一個圖片方盒,那麼,咱們接下來要讓它輪播起來,這些代碼和上一節的 3D slider 實現原理相似,不作具體講述,你們看看源碼就很容易理解了:
import React from 'react';
import './index.css';
export default class extends React.Component {
constructor(props) {
super(props);
this.index = 1;
this.container = React.createRef();
}
componentDidMount () {
// 獲取間隔時間,默認爲 2000 ms。
const delayTime = this.props.delayTime * 1000 || 2000;
// 獲取父容器
let parent = this.container.current.parentNode;
//獲取父容器的寬度
let width = this.props.width || parent.clientWidth;
//獲取父容器的高度。
let height = this.props.height || parent.clientHeight;
// 設置第一張圖片和第三張圖片的先後偏移。
let imgs = this.container.current.children;
imgs[0].style.transform = `translateZ(${height / 2}px)`;
imgs[2].style.transform = `translateZ(-${height / 2}px) rotateX(180deg)`;
// 設置輪播容器的尺寸
this.container.current.style.width = width + 'px';
this.container.current.style.height = height + 'px';
// 開始輪播
this.timer = setTimeout(this.loop.bind(this), delayTime);
this.container.current.addEventListener('transitionend', () => {
this.timer = setTimeout(this.loop.bind(this), delayTime);
})
}
loop () {
this.container.current.style.transform = 'rotateX(' + ((this.props.direction || 1) * this.index * 90) + 'deg)';
this.container.current.style.transition = (this.props.transitionTime || 2) + 's';
this.index++;
}
render () {
return <div className='container' ref={this.container}>
{this.props.imgList.map(item => {
return <img className='img-item' src={item.src} />
})}
</div>
}
}
複製代碼
自我測試比較簡單,就是將本身做爲一個用戶來模擬使用這個組件,模擬一切可能遇到的狀況進行測試,若是有問題,再進行修復。
分別將上面的構建結果提交到 github 的 master 和 gh-pages 分支。
最後一步就是發佈了,這裏也比較簡單,可是咱們要在package.json 中設置入口文件,設置 main 爲./dist/index.js
便可。
{
"name": "react-slider3d-fjj",
"version": "0.0.1",
"description": "",
"main": "./dist/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --mode=development",
"demo": "webpack --config ./webpack.config.js --progress --colors",
"build": "babel src -d dist --copy-files "
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel": "^6.23.0",
"babel-cli": "^6.26.0",
"babel-core": "~6.26.0",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"css-loader": "^2.1.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"source-list-map": "^2.0.1",
"style-loader": "^0.23.1",
"watchpack": "^1.6.0",
"webpack": "^4.29.5",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.2.1"
},
"dependencies": {
"react": "^16.8.3",
"react-dom": "^16.8.3"
}
}
複製代碼
以上就是我作的第三個小組件,都比較簡單,因爲本人還沒有畢業,因此能力有限,但願你們多提意見,將來我還會逐漸輸出一些新的組件供你們學習~~