接着一的内容,我们继续。之前准备工作以及舞台数据等都准备好了。
接下来,先对单个图片的布局样式设置好,在src/components的main.js里添加如下代码
//单个图片组件
class ImgFigure extends React.Component{
render(){
return(
);
}
}
然后在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({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(
);
}
}
至此,照片墙应该能随意展示了,但是运行之后又会报错
_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),
到这里,照片墙能正常显示。如下图
今天就到这里。