iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 23
0

Create New Component

  1. 在 gallery 顯示的地方新增 Gallery 元件,並匯入 Unsplash 的資料 <Gallery items='this.data' />
  2. 在空白處新增 Gallery 元件結構,建立 items 變數代替 props.items,這裡用到 ES6 的 destructuring 語法(我們在 import ReactDOM render function 時也有用過)。
const Gallery = (props) => {
  const { items } = props;
};

.map() 產生相簿 list group

  1. 來看一下 Unsplash 給我們的資料裡面的結構。我們需要 collection 的 cover photo 圖片連結來做相簿封面,以及 collection 的名稱.
  2. 使用 JavaScript .map() 將資料組合成 list group.
  3. React 在跑 map 迴圈時需要給每一個 item 一個特殊的 key 值,剛好資料裡有 id,就拿來用。
  4. 每個相簿的背景圖不一樣,我們直接在<a>加上 inline-style, React 的 style 值要以 object 的形式寫。
const Gallery = (props) => {
  const { items } = props;
  const el = items.map(item => (
    <li key={item.id} className={Style.item}>
      <a href="#" style={{ backgroundImage: `url(${item.cover_photo.urls.thumb})` }}>
        {item.title}
      </a>
    </li>));
  return <ul>{el}</ul>;
};

dynamic item width

前面我們偷懶,給 gallery item 固定的長寬,現在來依照 mockup 製作動態的寬度。
依照 mockup,在手機的尺吋一行會有四個相簿,我們要把瀏覽器的寬減去相簿之間的距離,再減去與左右兩邊的空間,除以一行的相簿數目,就是每個相簿該有的寬度。然後相簿要正方形,不管寬度怎麼變,高度也要跟著變,這些都可以用純CSS做到。

首先來計算寬度,由於還會有「照片」的區域,我們先用一個<div>包住相簿,並加上gallery的 class name,增加左右各 8px 的 padding.
相簿間距也是8px,所以是.gallery的總寬度減去三倍的8px再除以四,就是每個相簿該有的寬度。
再加上 padding-bottom 增加與下方的距離。

.gallery {
  margin: 0 8px;
}
.item {
  display: inline-block;
  width: calc((100% - 8px * 3)/4);
  margin-bottom: 8px;
}

接下來做相簿的高度,這邊用到一個原則「padding 百分比單位是由元素的寬度決定」,也就是說當元素任一邊padding為100%時,其長度和元素的寬度是一樣的,例如元素寬度是100px,padding-bottom: 100%也就等於padding-bottom:100px.

有了這個知識就能製作等比例縮放的方形,重點是在<li>裡面的<a>高度為0, padding-bottom:100%。寬度100%和父元素一樣。

.item a {
  font-size: 0;
  display: block;
  width: 100%;
  height: 0;
  padding-bottom: 100%;
  overflow: hidden;
  background-repeat: no-repeat;
  background-position: center center;
  background-size: cover;
}

最後來讓相簿水平排例,以往的做法會使用 float,這一次我們來用用 flexbox。
<ul>新增 className={Style['list-group']}, 並在app.css裡加入

.list-group {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

JSX裡不能有 hyphen 出現,如果class name有hyphen的話,就要用['class-name']的寫法,不能用 dot selector。

現在最後一行有了問題,如果不是剛好四個的話,相簿間距也會平均分配,如果在 flex-container 加入一個具有 flex 屬性的空白偽元素,能適時將多餘的空間填滿,但是最後一行相簿之間空隙也會消失。

.list-group:after {
  content: '';
  flex: auto;
}

解決方法是使用 CSS nth-child(an+b)nth-last-child(an+b)的組合技。讓最後一行多出左邊的margin。下面這段選擇語法意思是說「第1, 5, 9,... 個子元素,同時也是倒數第4,3,2,1個子元素,它之後同階層的元素,都加上margin-left:8px」。這邊的交集也只有第9個相簿符合,於是第10, 11, 12 個相簿會多出左邊margin。

.list-group .item:nth-child(4n+1):nth-last-child(-n+4) ~ .item {
  margin-left: 8px;
}

然後再使用 media query 加上其他螢幕大小的設定,自動化 gallery layout 就完成了!


上一篇
ESLint
下一篇
Photos
系列文
如何在前端開發流程中加入使用者經驗設計 - 以線上相簿為例30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言