前面写了两篇关于 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"
}
}
复制代码
以上就是我作的第三个小组件,都比较简单,因为本人还没有毕业,因此能力有限,但愿你们多提意见,将来我还会逐渐输出一些新的组件供你们学习~~