react-webpack 照片牆製作(二)

接着一的內容,我們繼續。之前準備工作以及舞臺數據等都準備好了。
接下來,先對單個圖片的佈局樣式設置好,在src/components的main.js裏添加如下代碼

//單個圖片組件
class ImgFigure extends React.Component{
  render(){
    return(
        <figure className="img-figure" >
          <img  src={this.props.data.imageURL} alt={this.props.data.title} />
          <figcaption>
            <h2 className="img-title">{this.props.data.title}</h2>
          </figcaption>
        </figure>

      );
  }
}

然後在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;
        }
      }
    }
}

效果如下圖
這裏寫圖片描述

到了這裏圖片會順序排到底部。我們接下來分析照片牆位置,獲取所有的位置信息。這裏也是按照慕課網分析的寫的。
在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(<ImgFigure key={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 (i<k) {
            imgsArrangeArr[i].pos = {
              left:  getRangeRandom(h_leftSecX[0],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(
        <figure className="img-figure" style={styleObj}>
          <img  src={this.props.data.imageURL} alt={this.props.data.title} />
          <figcaption>
            <h2 className="img-title">{this.props.data.title}</h2>
          </figcaption>
        </figure>

      );
  }
}

至此,照片牆應該能隨意展示了,但是運行之後又會報錯

_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),

到這裏,照片牆能正常顯示。如下圖

這裏寫圖片描述
今天就到這裏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章