大三学生的第三个基于 React 的 3D 轮播组件

栏目: 编程工具 · 发布时间: 5年前

内容简介:前面写了两篇关于 slider 组件如何实现的文章,有兴趣的朋友可以点击这里目前在找实习工作,有合适的机会希望小伙伴们多多推荐~本文最终的 3D 轮播效果如下图:

前面写了两篇关于 slider 组件如何实现的文章,有兴趣的朋友可以点击这里 原生 slider 组件的实现React slider组件的实现 查看,今天写一篇关于 3D 轮播图实现原理的文章。

目前在找实习工作,有合适的机会希望小伙伴们多多推荐~

正文开始

本文最终的 3D 轮播效果如下图:

大三学生的第三个基于 React 的 3D 轮播组件

依然参照原来的思路,按照一个正规的项目来对待,我们还是按照如下过程来实现。

  • 需求文档
  • 设计方案
  • 编码实现
  • 自我测试
  • 提交到 github
  • 发布 npm 包

需求文档

因为我们是要实现一个 3D 轮播组件,所以不可避免地要使用一些 3D 属性,除了在 W3CSchool 上学习,我还买了本小册WebGL 入门与实践,虽然这是本讲解 Webgl 的小册,但是这本小册也开辟了几个章节讲述 CSS3 中 3D 属性的用法,给我带来了一些新的思路。

列举一下我们的需求:

  • 使用者传入四张图片,能够实现 3D 轮播效果,支持向上轮播和向下轮播的方向配置。
  • 可以配置尺寸。
  • 可以配置轮播持续时间。
  • 可以配置轮播间隔时间。
  • 可以通过 npm install 的方式安装使用。

需求比较简单,核心就是 3D 轮播效果。

设计方案

产品的需求到了,那么作为开发人员,要开始思考如何实现产品的需求了,除此之外,还需要考虑未来产品的意图,按照这个思路,我又想到了一些配置项,前面也讲过,这些都是隐含的开发需求:

  • 针对以上的配置要设置一个默认参数:
    • 方向配置,默认为 1,即向上转动。
    • 尺寸配置,默认为父容器的尺寸。
    • 轮播持续时间,默认为 2 秒。
    • 轮播间隔时间,默认为 2 秒。

那么我们要开始写设计方案了。

  • 需求关键: 关键需求就是根据传入的四张图片实现 3D 轮播效果。
  • 视觉关键: 暂无。
  • 交互关键: 暂无。
  • 性能关键:这里我目前只想到:如果图片的尺寸过大,那么可能还未加载出来就已经开始转动了,需要在图片全部加载到本地之后再开始轮播。本期暂不做优化。

具体实现

实现主要就是利用 css3 transform 属性的 translateY 和 translateZ 值,将四张图片通过前移后移、上移、下移组成一个图片方盒。 拿四张 300px 高的图片举例。

  • 父容器要设置 transform-style 为 preserve-3d 才可以让子元素展示出 3D 效果:
.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>
  }
}
复制代码

自我测试

自我测试比较简单,就是将自己作为一个用户来模拟使用这个组件,模拟一切可能遇到的情况进行测试,如果有问题,再进行修复。

构建

  • 执行 npm run build 构建出可供大家引入的 index.js
  • 执行 npm run demo 构建出可供大家预览的页面。

提交到 git

分别将上面的构建结果提交到 github 的 master 和 gh-pages 分支。

  • git add ./
  • git commit -m '...'
  • git push origin master
  • git checkout -b gh-pages
  • git push origin 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"
  }
}
复制代码

小结

以上就是我做的第三个小组件,都比较简单,由于本人尚未毕业,所以能力有限,希望大家多提意见,未来我还会逐渐输出一些新的组件供大家学习~~


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

思想的未来

思想的未来

(美)劳伦斯﹒莱斯格 / 李旭 / 中信出版社 / 2004-10 / 29.00元

因特网革命已到来,一些人说它已经过去,革命缘何而来?又缘何而去呢? 劳伦斯·莱斯格对因特网革命中为何会出现一种反革命的破坏性力量及后果做出了解释。创作之所以繁荣,是因为因特网保护了创新的公共资源。是因为因特网保护了创新的公共资源。因特网的独特设计营造出一个中立的平台。最广大范围的作者们可在此平台上进行试验。围绕此平台的法律架构对这一自由空间给予了保护,以使文化和信息——我们这个时代的......一起来看看 《思想的未来》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具