画像の読み込みを制することでイライラをなくす
自分のwiki の転記です。
Code
環境
お試しのため create react app を使っている
$ npx create-react-app my-app
$ cd my-app
$ npm start
コード
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Loading Spinner</h1>
<img alt="" src="https://penguin-ogp.vercel.app/api/ogp?text=こんにちは人類" />
<p>イメージを表示します</p>
</header>
</div>
);
}
export default App;
表示する画像は https://github.com/itizawa/penguin-ogp で生成したもの。
このコードには読み込み時の問題がある。
読み込みが遅い環境の場合、「イメージを表示します」のメッセージが読み込まれた画像によってその分だけ下にずれる。
改善するために、img に height と width を指定しようとするがうまくは行かない
うまく行かない指定
<img width="100%" height="auto" alt="" src="https://penguin-ogp.vercel.app/api/ogp?text=こんにちは人類" />
読み込み後に初めて width と height の情報が得られるため、初めからその画像分の幅を取ることはできない。
縦横比を指定して読み込み前に幅を指定する
create react app では sass が使えないため、
$ yarn add node-sass
を実行しインストールしておく。
元の画像は、 w1200, h660 なので、高さ 1 に対して横幅は 0.55。
それを踏まえたコードが次のようになる。
js
import React from 'react';
import './App.scss';
function App() {
return (
<div className="App">
<div className="App-container">
<h1>Loading Spinner</h1>
<div className="fix-aspect-box">
<img alt="" src="https://penguin-ogp.vercel.app/api/ogp?text=こんにちは人類" />
</div>
<p>イメージを表示します</p>
</div>
</div>
);
}
export default App;
scss
.fix-aspect-box {
position: relative;
width: 100%;
padding-top: 55%;
img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
イメージは初めに額縁を用意しておいて、後から届いた画像を収まるように収縮して当てはめるという感じ。
縦横比を指定しているから小さくなっても画像が引き伸ばされたりはしない。
最後に spinner を追加する。
先ほどの状態だと、無の空間にいきなり画像が表示される。
想定していないものがいきなり現れるのは気持ちの良いものではない。
そこで読み込み中は spinner を表示する。
https://design.webclips.jp/svg-loading-icon/
public に svg を配置しbackground-image
で読み込むことができる。
.fix-aspect-box {
position: relative;
width: 100%;
padding-top: 55%;
img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
// show spinner
background-image: url('/spinner.svg');
background-repeat: no-repeat;
background-position: center center;
}
}
完成