基于flexbox中的行动态调整元素大小

时间:2016-09-01 01:59:57

标签: javascript css reactjs flexbox

我正在尝试根据每个元素落在Flexbox容器中的哪一行动态更改按钮大小,类似于:

Internet Radio Genre example

我正在使用ReactJS并创建了一个包含各种类型的数组,我希望这个数组可以调整大小。我正在映射数组以创建每个按钮,如下所示:

class ButtonContainer extends React.Component {
  constructor(props) {
    super(props);
  };
  render() {
    let items = this.props.data;
    let anItem = items.map((item, i) => {
      return (
      <button className='singleButton'>{item}</button>
    )
    });
    return (<div className='buttonContainer'>{anItem}</div>)
  }
}

和CSS:

.buttonContainer {
  display:flex;
  flex-flow: row wrap;
  justify-content: space-around;
  margin-top:1.5rem;
}

我想知道是否有办法选择使用JS或CSS在特定断点之后落入哪些项目?可能只有一种完全不同的方式可以解决这个问题。

JSFiddle example

谢谢!

1 个答案:

答案 0 :(得分:0)

在JavaScript中,您可以通过各种方式获取元素的当前位置。其中之一是element.getBoundingClientRect()。一旦你可以在页面上为元素<button>元素设置Y位置,就可以确定行中断的位置。

在下面的代码中,当Y位置值从一个被更改的元素更改为下一个元素时,确定行中断超过slopY。我们知道我们从顶行开始,从右到左,从上到下。它也适用于从左到右的显示。只有从上到下的遍历很重要。关键是我们知道在遇到第二行中的任何一行之前我们处理第一行中的所有按钮,等等。

代码将不同的类应用于每行中的元素(<buttons>)。此外,为了进行测试,它会更改高度并为每行中的按钮应用不同的背景颜色。

当布局更改时,按钮不会使用正确的类(或应用于测试的大小和颜色)自动维护。因此,如果按钮更改布局(例如,它们所在的容器已调整大小),则需要重新运行applyRowClassesMultipleTimes()。这可以通过添加适当的事件处理程序来处理。

在简单尝试中,我没有让ReactJS与Stack Overflow片段中的代码一起运行。因此,对于下面的代码片段,我只是复制了代码在您链接的JSFiddle中生成的DOM。

以下代码也是available as a JSFiddle,其中包含您的ReactJS代码。

function applyRowClasses(buttonSelector,rowClassBase){
  //The selector passed as the first argument should select all elements for which
  //  it is desired to have the class applied.
  //The second argument is the text portion of the class to be applied. The row
  //  number (0 at the top) will be appended to that text for the class of each row.
  //  (e.g. 'row' will result in classes 'row0', 'row1', 'row2', etc.)

  var children = document.querySelectorAll(buttonSelector);
  var replaceRowRegExp = new RegExp('\\s*' + rowClassBase + '\\d+(\\b|$)','g');
  var child;
  var testColor = ['red','orange','yellow','green','blue','purple','crimson'
                   ,'cyan','lightgreen','lightblue','Fuchsia'];
  var row = -1;
  var rowY = 0;
  var slopY = 5;
  var newHeight = 120;
  var newHeightDelta = -10;
  for(var i=0,numChildren=children.length;i<numChildren;i++) {
    child = children[i];
    var rect = child.getBoundingClientRect();
    if(rect.top > rowY+slopY){
      //New row
      row++;
      rowY = rect.top;
      newHeight += newHeightDelta;
    }
    var childClass = child.className;
    //Remove any old row class.  Need to do this because we would need to re-apply
    //  these classes when the window size changes, or if the layout changes
    //  in response to the changes we are making here.
    childClass = childClass.replace(replaceRowRegExp,'');
    childClass += ' ' + rowClassBase + row;
    child.className = childClass;
    //For testing change background color and height
    child.style.backgroundColor = testColor[(row % testColor.length)];
    child.style.height = newHeight + 'px';
  }
}

function applyRowClassesMultipleTimes(buttonSelector,rowClassBase,count){
  //Our changes may affect the button layout. Change
  //  multiple times giving the browser a chance to re-draw.
  //  We could calculate what our changes will be, but it's just as
  //  easy to iterate a few times.
  if(count<=1){
    return;
  }
  applyRowClasses(buttonSelector,rowClassBase);
  count--;
  setTimeout(applyRowClassesMultipleTimes,0,buttonSelector,rowClassBase,count);
}

applyRowClassesMultipleTimes('#root button','row',4);
#root {
  display:flex;
  color:#444;
}

.buttonContainer {
  display:flex;
  flex-flow: row wrap;
  justify-content: space-around;
  margin-top:1.5rem;
}
<body>
<div xmlns="http://www.w3.org/1999/xhtml" id="root"><div data-reactroot=""><div>Popular Genres</div><div class="buttonContainer"><button class="singleButton">Jazz</button><button class="singleButton">Top 40</button><button class="singleButton">Country</button><button class="singleButton">Blues</button><button class="singleButton">Easy Listening</button><button class="singleButton">Rock</button><button class="singleButton">Classical</button><button class="singleButton">Chillout</button><button class="singleButton">80s</button><button class="singleButton">Oldies</button><button class="singleButton">Dance</button><button class="singleButton">Ambient</button><button class="singleButton">Reggae</button><button class="singleButton">Trance</button><button class="singleButton">Hip Hop</button><button class="singleButton">Smooth Jazz</button><button class="singleButton">70s</button><button class="singleButton">House</button><button class="singleButton">Lounge</button><button class="singleButton">Drum and Bass</button><button class="singleButton">Metal</button><button class="singleButton">Meditation</button><button class="singleButton">Heavy Metal</button><button class="singleButton">60s</button><button class="singleButton">Techno</button><button class="singleButton">Pop</button><button class="singleButton">Soul</button><button class="singleButton">90s</button><button class="singleButton">Psytrance</button><button class="singleButton">Latin</button><button class="singleButton">Funk</button><button class="singleButton">Rap</button><button class="singleButton">Bollywood</button><button class="singleButton">50s</button><button class="singleButton">Hindi</button><button class="singleButton">Rockabilly</button><button class="singleButton">Minimal</button><button class="singleButton">Greek</button><button class="singleButton">Comedy</button><button class="singleButton">Alternative</button><button class="singleButton">Reggaeton</button><button class="singleButton">New Age</button><button class="singleButton">Salsa</button><button class="singleButton">Bluegrass</button><button class="singleButton">edm</button><button class="singleButton">Manele</button><button class="singleButton">Indie</button><button class="singleButton">Japanese</button><button class="singleButton">Dancehall</button><button class="singleButton">Classic Rock</button><button class="singleButton">Disco</button><button class="singleButton">Dubstep</button><button class="singleButton">Folk</button><button class="singleButton">goth</button><button class="singleButton">Punk</button><button class="singleButton">Garage</button><button class="singleButton">New Wave</button></div></div></div>
</body>

以下是不使用颜色和尺寸时按钮的外观:

#root {
  display:flex;
  color:#444;
}

.buttonContainer {
  display:flex;
  flex-flow: row wrap;
  justify-content: space-around;
  margin-top:1.5rem;
}
<body>
<div xmlns="http://www.w3.org/1999/xhtml" id="root"><div data-reactroot=""><div>Popular Genres</div><div class="buttonContainer"><button class="singleButton">Jazz</button><button class="singleButton">Top 40</button><button class="singleButton">Country</button><button class="singleButton">Blues</button><button class="singleButton">Easy Listening</button><button class="singleButton">Rock</button><button class="singleButton">Classical</button><button class="singleButton">Chillout</button><button class="singleButton">80s</button><button class="singleButton">Oldies</button><button class="singleButton">Dance</button><button class="singleButton">Ambient</button><button class="singleButton">Reggae</button><button class="singleButton">Trance</button><button class="singleButton">Hip Hop</button><button class="singleButton">Smooth Jazz</button><button class="singleButton">70s</button><button class="singleButton">House</button><button class="singleButton">Lounge</button><button class="singleButton">Drum and Bass</button><button class="singleButton">Metal</button><button class="singleButton">Meditation</button><button class="singleButton">Heavy Metal</button><button class="singleButton">60s</button><button class="singleButton">Techno</button><button class="singleButton">Pop</button><button class="singleButton">Soul</button><button class="singleButton">90s</button><button class="singleButton">Psytrance</button><button class="singleButton">Latin</button><button class="singleButton">Funk</button><button class="singleButton">Rap</button><button class="singleButton">Bollywood</button><button class="singleButton">50s</button><button class="singleButton">Hindi</button><button class="singleButton">Rockabilly</button><button class="singleButton">Minimal</button><button class="singleButton">Greek</button><button class="singleButton">Comedy</button><button class="singleButton">Alternative</button><button class="singleButton">Reggaeton</button><button class="singleButton">New Age</button><button class="singleButton">Salsa</button><button class="singleButton">Bluegrass</button><button class="singleButton">edm</button><button class="singleButton">Manele</button><button class="singleButton">Indie</button><button class="singleButton">Japanese</button><button class="singleButton">Dancehall</button><button class="singleButton">Classic Rock</button><button class="singleButton">Disco</button><button class="singleButton">Dubstep</button><button class="singleButton">Folk</button><button class="singleButton">goth</button><button class="singleButton">Punk</button><button class="singleButton">Garage</button><button class="singleButton">New Wave</button></div></div></div>
</body>