何の話かと言うと
上記の続きになります。今回からは、いよいよ Reversi の実装に入ります。まずは、画面の背景に Reversi のボードを表示することにしましょう。
アプリケーションのコードを用意
まずは、これまでと同様にアプリケーションの雛形を作成します。
% npx create-react-app react_reversi % cd react_reversi
今回は、見た目も綺麗にしたいので、React の UI コンポーネントを提供する Chakra UI と関連するパッケージを追加しておきます。
% yarn add @chakra-ui/react @chakra-ui/icons @emotion/react @emotion/styled framer-motion
この後、ディレクトリー「public」と「src」の中身をごっそり削除して、下記の内容に入れ替えます。
public/ ├── favicon.ico └── index.html src/ ├── assets │ ├── black.png │ ├── blank.png │ ├── board.png │ └── white.png ├── components │ ├── Board.js │ └── Layout.js ├── index.js └── theme └── theme.js
実際のファイルの中身は、下記のリポジトリ(v0.1 ブランチ)から参照することができます。
個別にファイルをコピーするのが面倒な場合は、次のコマンドで上記のリポジトリをクローンして再現することもできます。
% cd ~/Documents/work % git clone https://github.com/enakai00/react_reversi % cd react_reversi % git checkout v0.1
次のコマンドで、必要なパッケージをインストールして開発用サーバーを起動すると・・・
% yarn install % yarn start
めでたくボードが表示されます。
ファイルの説明
個々のファイルの内容を説明していきます。
画像ファイル
このアプリケーションで使う画像ファイルは、ディレクトリー「src/assets」にまとめて保存してあります。この後で見るように、src 以下に配置した画像ファイルは、コードの中でオブジェクトとしてインポートして使用します。
src/ ├── assets │ ├── black.png ← 黒ゴマ │ ├── blank.png ← 透明ファイル(コマの無い場所に表示) │ ├── board.png ← ボード │ └── white.png ← 白ゴマ
index.html
前回の Hello, World! アプリケーションとほぼ同じで、ID が "root" の dvi 要素を用意しているだけです。
index.js
import React from 'react'; import ReactDOM from 'react-dom/client'; import { ChakraProvider } from "@chakra-ui/react"; import theme from "./theme/theme"; import { Layout } from './components/Layout'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <ChakraProvider theme={theme}> <Layout /> </ChakraProvider> );
ここでは、先にインストールした Chakra UI のコンポーネントを利用しています。背景色やデフォルトのフォントサイズなど、UI のデザインに関わる基本設定が「src/theme/theme.js」に記載されており、これがすべてのコンポーネントに適用されます。また、ここでは、「components/Layout.js」で定義した Layout コンポーネントを画面に配置しています。
Layout.js
このファイルでは、ゲームの盤面、得点表、操作ボタンなどのコンポーネントを画面上に適切に配置しますが、今回は、ゲームの盤面を表す Board コンポーネントだけを配置しています。
import React from "react"; import { Container, Stack, Heading, Box } from "@chakra-ui/react"; import { Board } from "./Board"; export const Layout = (props) => { const element = ( <Container padding="8"> <Stack spacing="1"> <Heading marginLeft="4" fontSize="3xl">Reversi</Heading> <Box> <Board/> </Box> </Stack> </Container> ); return element; }
「Container」「Stack」「Heading」「Box」などは、Chakra UI が提供するコンポーネントです。Box は HTML の div 要素に対応するもので、基本的には、Box の子コンポーネントとして、実際に何かを表示するコンポーネントを配置します。Heading はヘッダーを配置します。そして、その他のコンポーネントは、これらの表示位置をコントロールします。今回は、Continer で中央寄せの表示領域を用意して、その中で、Stack コンポーネントを使って、ヘッダーと Board を縦に積み重なるように配置しています。padding や spacing などの属性値は、名前から役割が想像できると思います。詳細については、Chakra UI のドキュメントを参照してください。
ここで、関数 Layout は、引数 props を持っている点に注意してください。今回のコードでは、props の値は使用していませんが、一般には、上位コンポーネントで Layout を配置した際の属性値を props で受けることができます。たとえば、
<Layout x={1} y={2} />
という形で Layout を配置すると、関数 Layout 内では、prop.x および prop.y として、x と y の値(今の場合は、1 と 2)を参照できます。さらにちなみに、上記では「{1}」のように、渡したい値に波括弧がついていますが、一般に、波括弧の内部には、Javascript のコードを配置することができて、コードの評価値を渡すことができます。今回は、数値そのものをコードとして記載していますが、変数を配置すれば、変数に格納された値(一般には、オブジェクトのリファレンス)を渡すことができます。
Board.js
これが今回のメインのコードとなります。
import React from "react"; import { Box } from "@chakra-ui/react"; import board from "../assets/board.png"; export const Board = (props) => { const style = { position: "relative", width: "584px", height: "592px", backgroundRepeat: "no-repeat", backgroundPosition: "center", backgroundImage: `url(${board})`, backgroundSize: "100%" }; const element = ( <Box style={style}> </Box> ); return element; }
このコードでは、中身のない Box コンポーネントを配置していますが、style オプションにより背景画像を設定しており、これで、先ほどのボードが表示されます。この style オプションの使い方は、「インラインスタイル」と呼ばれるもので、CSS ファイルを用意せずにコード内で直接にスタイルを設定することができます。設定内容は、事前に連想配列 style として用意しておき、この内容を(先に説明した波括弧記法を用いて)属性値として渡します。
背景画像の実態は、事前に board という名前でインポートしてあり、${board} は画像ファイルのパスに対応します。これをスタイルの backgroundImage 要素に指定することで、めでたくボードの画像が表示されるというわけです。