react-webpack 照片墙制作(二)

接着一的内容,我们继续。之前准备工作以及舞台数据等都准备好了。
接下来,先对单个图片的布局样式设置好,在src/components的main.js里添加如下代码

//单个图片组件
class ImgFigure extends React.Component{
  render(){
    return(
        
"img-figure" > this.props.data.imageURL} alt={this.props.data.title} />

"img-title">{this.props.data.title}

); } }

然后在app.scss里添加样式,这个是在.img-sec下的,

.img-sec {
    position: relative;

    width: 100%;
    height: 90%;
    overflow: hidden;

    background-color: #ddd;
    /*****添加代码*******/
    @at-root{
      .img-figure{
        position: absolute;

        width: 320px;
        height: 360px;
        margin: 0;
        padding: 40px;
        background-color: #fff;
        box-sizing: border-box;
      }
      figcaption{
        text-align: center;

        .img-title{
          margin:20px 0 0 0;
          color: #a7a0a2;
          font-size: 16px;
        }
      }
    }
}

效果如下图
react-webpack 照片墙制作(二)_第1张图片

到了这里图片会顺序排到底部。我们接下来分析照片墙位置,获取所有的位置信息。这里也是按照慕课网分析的写的。
在main.js 里的AppComponent组件里添加函数如下,代码中的rearrange函数为重新排布位置函数,后续有相关补充。

componentDidMount(){
      /**舞台的宽高以及半宽半高**/
      var stageDOM = React.findDOMNode(this.refs.stage),
            stageW = stageDOM.scrollWidth,
            stageH = stageDOM.scrollHeight,
            halfStageW = Math.ceil(stageW/2),
            halfStageH = Math.ceil(stageH/2);
        //图片的宽高以及半宽半高
        var imgDOM = React.findDOMNode(this.refs.imgFigure0),
            imgW = imgDOM.scrollWidth,
            imgH = imgDOM.scrollHeight,
            halfImgW = Math.ceil(imgW/2),
            halfImgH = Math.ceil(imgH/2);


      /**中央图片的位置**/
      this.Constant.centerPos = {
          left: halfStageW - halfImgW,
          top: halfStageH - halfImgH
      };
  /**水平方向上左右两侧图片范围start**/
      /**左**/
      this.Constant.hPosRange.leftSecX[0] = -halfImgW;
      this.Constant.hPosRange.leftSecX[1] = halfStageW - halfImgW * 3;
      /**右**/
      this.Constant.hPosRange.rightSecX[0] = halfStageW + halfImgW;
      this.Constant.hPosRange.rightSecX[1] = stageW - halfImgW;
      /**垂直**/
      this.Constant.hPosRange.h_y[0] = -halfImgH;
      this.Constant.hPosRange.h_y[1] = stageH - halfImgH;
  /**水平方向上左右两侧图片范围end**/
 /**垂直方向上顶部图片范围start**/
      this.Constant.vPosRange.v_x[0] = halfStageW - imgW;
      this.Constant.vPosRange.v_x[1] = halfStageW;
      this.Constant.vPosRange.v_y[0] = -halfImgH;
      this.Constant.vPosRange.v_y[1] = halfStageH - halfStageH*3;
  /**垂直方向上顶部图片范围end**/
      /**默认居中第一章图片**/
      this.rearrange(0);
  }

当然,这里需要在AppComponent里添加Constant变量,不能按照视频里的写,因为此处用的是ES6的模式的写的react,所以按照视频里的步骤会报错。
在AppComponent组件里直接声明的变量无法获取,应该在AppComponent里添加constructor(props) 函数,代码如下

constructor(props) {
        super(props);
         /***位置范围常量***/
        this.Constant= {
          centerPos:{
            left:0,
            top: 0
          },
          hPosRange:{
            leftSecX:[0,0],
            rightSecX:[0,0],
            h_y:[0,0]
          },
          vPosRange:{
            v_x:[0,0],
            v_y:[0,0]
          }
        };
    }

所有位置获取之后,我们得给图片一个放置位置的地方,需要初始化一个对象,按照视频里的代码如下

//初始化数据
  getInitialState(){
    //初始化图片位置信息
    return({
        imgsArrangerArr:[]
    });
  }

在render里添加

var controllerUnits=[],
        that = this,
        imgFigures=[];
    imageDates.map(function(value,index){
          //如果图片的位置信息不存在的话,初始化所有图片位置
          if (!that.state.imgsArrangeArr[index]) {
            that.state.imgsArrangeArr[index]={
                pos:{
                  left:0,
                  top:0
                }
            }
        }
        imgFigures.push({index} data={value} arrange={this.state.imgsArrangeArr[index]} ref={'imgFigure'+index} />);
      }.bind(this));

但是运行之后会提示错误:

Warning: getInitialState was defined on DimensionPicker, a plain JavaScript
class. This is only supported for classes created using React.createClass. Did
you mean to define a state property instead?

这是因为在ES6的classes里面getInitialState函数已经抛弃,我们设置state需在constructor函数里面。删除getInitialState修改如下:

constructor(props) {
        super(props);
        this.state = { imgsArrangeArr: []};
        this.Constant= {
          centerPos:{
            left:0,
            top: 0
          },
          hPosRange:{
            leftSecX:[0,0],
            rightSecX:[0,0],
            h_y:[0,0]
          },
          vPosRange:{
            v_x:[0,0],
            v_y:[0,0]
          }
        };
    }

接下来,我们按照视频里的分析,写出了rearrange函数,代码如下:

 var imgsArrangeArr = this.state.imgsArrangeArr, //获取图片位置信息数组
          Constant = this.Constant,                   //获取定位位置对象
          centerPos = Constant.centerPos,             //获取  居中位置信息
          hPosRange = Constant.hPosRange,             //获取  水平位置信息
          h_leftSecX = hPosRange.leftSecX,              //获取  左侧x位置信息
          h_rightSecX= hPosRange.rightSecX,             //获取  右侧x位置信息
          h_y = hPosRange.h_y,                          //获取  y位置信息
          vPosRange = Constant.vPosRange,             //获取  顶部位置信息
          v_x = vPosRange.v_x,                          //获取  顶部x位置信息
          v_y = vPosRange.v_y;                          //获取  顶部y位置信息

      //获取居中图片index并居中处理
      var imgsArrangeArrCenter = imgsArrangeArr.splice(centerIndex,1);
          imgsArrangeArrCenter.pos= centerPos;
      //获取顶部图片index并处理
      var topImgNum = Math.ceil(Math.random()*2),
          topIndex = 0,
          imgsArrangeArrTop = [];
          if (topImgNum) {
            topIndex = Math.ceil(Math.random()*(imgsArrangeArr.length-topImgNum+1));
            imgsArrangeArrTop = imgsArrangeArr.splice(topIndex,topImgNum);
            imgsArrangeArrTop.forEach(function(value,index){
              imgsArrangeArrTop[index].pos={
                left: getRangeRandom(v_x[0],v_x[1]),
                top: getRangeRandom(v_y[0],v_y[1])
              };
            });
          }
      //获取水平方向上的图片信息并处理
      var k = Math.ceil(imgsArrangeArr.length/2);
      for (var i = 0; i <  imgsArrangeArr.length; i++) {
          if (i0],h_leftSecX[1]),
              top: getRangeRandom(h_y [0],h_y [1])
            }
          }else{
            imgsArrangeArr[i].pos = {
              left: getRangeRandom(h_rightSecX[0],h_rightSecX[1]),
              top: getRangeRandom(h_y [0],h_y [1])
            }
          }
      }

      //将取出的数组元素修改之后放回去
      //顶部图片
      if (imgsArrangeArr && imgsArrangeArrTop) {
        for (var i = topImgNum-1; i >= 0; i--) {
           imgsArrangeArr.splice(topIndex,0,imgsArrangeArrTop[i]);
        }
      }
      //中间图片
      imgsArrangeArr.splice(centerIndex,0,imgsArrangeArrCenter);

      this.setState({
          imgsArrangeArr: imgsArrangeArr
      })

这里稍微做了一下修改,按照视频里的顶部区域只能是0张或者1张照片,如果修改了随机底数,大于1了,顶部的处理代码无法满足。

然后在main.js 里添加getRangeRandom函数以及修改ImgFigure组件,代买如下

/*
 * 取范围内的随机整数
 * @param  low,high
 */
 function getRangeRandom(low,high) {
     return Math.ceil(Math.random()*(high-low)+low);
 }
//单个图片组件
class ImgFigure extends React.Component{
  render(){
    var styleObj={};
    //如果props属性中指定了这张图片的位置,则使用
    if (this.props.arrange.pos) {
      styleObj = this.props.arrange.pos;
    }
    return(
        
"img-figure" style={styleObj}> this.props.data.imageURL} alt={this.props.data.title} />

"img-title">{this.props.data.title}

); } }

至此,照片墙应该能随意展示了,但是运行之后又会报错

_reactDom2.default.render is not a function

这里是因为componentDidMount组件中的findDOMNode出问题了。

当我们需要获取 React 组件上某个 DOM 节点时,React 提供了 refs 方法方便我们快速引用。为了方便我们使用,React 还「贴心」地对 refs 做了一层封装,使用 this.refs.xxx.getDOMNode() 或 React.findDOMNode(this.refs.xxx) 可以获取到真正的 DOM 节点。

结果发现大家真正需要的就是 DOM 节点本身,封装了半天完全是浪费感情。

于是在 v0.14 版中 refs 指向的就是 DOM 节点,同时也会保留 .getDOMNode() 方法(带 warning),最终在 v0.15 版中去除该方法。

之前要用
React.findDOMNode(this.refs.xxx)或者this.refs.xxx.getDOMNode() 获取DOM节点
现在直接用
this.refs.xxx就能获取

这是我在网上找到了,但是修改之后发现,组件上的ref定义之后用this.refs.xxx获取的不是虚拟dom节点,获取的是Compoennt实例,ref添加到原生HTML上获取的才是DOM,所以代买修改如下时会报错..原因是imgDOM 获取的是Compoennt实例,后面的imgW ,imgH 等无法获取数值,是空的,所以报错。

//舞台的宽高以及半宽半高
      var stageDOM = this.refs.stage,
          stageW = stageDOM.scrollWidth,
          stageH = stageDOM.scrollHeight,
          halfStageW = Math.ceil(stageW/2),
          halfStageH = Math.ceil(stageH/2);

      //图片的宽高以及半宽半高
      var imgDOM = this.refs.imgFigure0,
          imgW = imgDOM.scrollWidth,
          imgH = imgDOM.scrollHeight,
          halfImgW = Math.ceil(imgW/2),
          halfImgH = Math.ceil(imgH/2);

经过几番查找,终于找到如何将Compoennt实例转化为DOM节点了,
在main.js中需要在顶部添加

import ReactDOM from 'react-dom';

然后对imgDOM = this.refs.imgFigure0
修改如下

var imgDOM = ReactDOM.findDOMNode(this.refs.imgFigure0),

到这里,照片墙能正常显示。如下图


今天就到这里。

你可能感兴趣的:(React学习)