この記事は「【マイスター・ギルド】本物のAdvent Calendar 2022」5日目の記事です。
他の記事も要チェックや!!
はじめに
みなさまこんにちは。sawaです。
「はよ犬ガチャを回させんかい!」という、犬ジャンキーの方は早速下のリンクからどうぞ。
犬ってかわいいですよね。
時間に余裕があってもなくても犬を見て癒されている方は多いんじゃないでしょうか。
今日はそんな犬の画像を提供してくれるAPIを紹介したいと思います。
ただ紹介するだけでは面白くないので、今回はReactで10連ガチャ風に実装してみました。
なぜReactなのかというと、勉強中だからです。
なぜ10連ガチャ風なのかというと、10連ガチャをたくさん回せて犬も見れるとなるととっても嬉しいからです。
対戦よろしくお願いします。
犬APIについて
犬好きの皆様にぜひ知っていただきたいAPIがあります。
その名は「DogAPI」。そのまんまですね。
これはスタンフォード大学が提供している犬の画像のデータセットを、有志がAPIで取得できるようにしてくれたものです。
犬種別に取得できたり、エンドポイントに数字を指定して複数取得できたりします。
ブラウザ上で試せるので、自分で試したい方はリンク先へどうぞ。
また、自分ちの犬の写真をPRで投げると追加してくれるらしいです。
犬飼いエンジニアの方は参加してみてはいかがでしょうか。
Reactで10連ガチャ風に実装する
早速作っていきましょう。
犬APIを叩く
まずは犬APIを叩きます。
import { useEffect, useState } from "react";
import axios from "axios";
export const DogCard = () => {
const [posts, setPosts] = useState([]);
//APIを叩いてpostsにJSONデータを格納
useEffect(() => {
axios.get("https://dog.ceo/api/breeds/image/random/10").then((res) => {
setPosts(res.data.message);
});
}, [setPosts]);
return (
<SDogCard>
<ul>
{posts.map((post, i) => {
return (
<li key={i} >
<img src={post} width={500} alt="犬の画像" loading="lazy" />
</li>
);
})}
</ul>
</SDogCard>
);
};
結果
補足
-
https://dog.ceo/api/breeds/image/random/10
と、エンドポイントに「10」と指定することで10枚の画像を取得しました。10連ガチャだからね。 - 取得した画像の大きさがバラバラなので、一旦
<img src={post} width={500} alt="犬の画像" loading="lazy" />
としてwidthを指定しています。とりあえずの処置なので後で調整します。
ボタンの実装
上述した実装方法だと画面更新で画像が切り替わるのですが、それでは味気ないので画像を表示するボタンを実装していきます。
「初回の結果を表示するボタン」と、「2回目以降の結果を表示するボタン」の2種類を作ります。
初回の結果を表示するボタンの実装
export const Top = () => {
const [showDogImageFlag, setShowDogImageFlag] = useState(false);
const onClickShowDogImage = () => {
setShowDogImageFlag(!showDogImageFlag);
};
return (
<STop>
<h1 className="title">犬無料10連ガチャ</h1>
<div
className="showResultArea"
showresult={showDogImageFlag ? "false" : "true"}
>
<DogCard />
</div>
<div className="showResultButtonArea">
<input
type="button"
value="回す!"
onClick={onClickShowDogImage}
className="showResultButton"
showresult={showDogImageFlag ? "false" : "true"}
/>
</div>
</STop>
);
};
/*犬の画像を表示/非表示*/
.showResultArea[showresult="false"] {
display: inline-block;
padding: 20px;
}
.showResultArea[showresult="true"] {
display: none;
}
/*ボタンを表示/非表示*/
.showResultButton[showresult="true"] {
display: inline-block;
}
.showResultButton[showresult="false"] {
display: none;
}
結果
サイトの初回表示時にこの画面が表示されます。
この赤矢印で示しているボタンを押すと結果が表示されます。
補足
- ボタンを押すと
showDogImageFlag
の真偽値が切り替わるようになっています。それを受けてCSSで犬画像とボタンの表示非表示を制御しています。 - タイトルやボタンのスタイルは適当にCSSを当てています。グラデーションを設定するだけで情報量が多くなるので適当にそれっぽいスタイルを当てたいときにオススメです。
2回目以降の結果を表示するボタンの実装
export const DogCard = () => {
const [posts, setPosts] = useState([]);
+ const [renew, setRenew] = useState("");
//APIを叩いてpostsにJSONデータを格納
useEffect(() => {
axios.get("https://dog.ceo/api/breeds/image/random/10").then((res) => {
setPosts(res.data.message);
});
- }, [setPosts]);
+ }, [setPosts, renew]);
return (
<SDogCard>
<ul>
{posts.map((post, i) => {
return (
<li key={i}>
<img src={post} alt="犬の画像" loading="lazy" />
</li>
);
})}
</ul>
+ <input
+ type="button"
+ value="もう一回!"
+ onClick={() => setRenew((renew) => renew + 1)}
+ />
</SDogCard>
);
};
結果
赤矢印で指し示しているボタンを押すと、新しい結果画面が読み込まれます。
補足
- 「もう一回!」ボタンを押す度にAPIが叩かれるように、新たにstateを追加しました。
こちらは下記サイト様を参考にさせていただきました。ありがとうございます!
CSSで結果画面をガチャっぽくする
ガチャの結果画面で気になるものといえば、そう、レアリティですね。
それを画像の左上に重ねて、画像の大きさを均一にしたりします。
おお!一気にガチャっぽくなりましたね。
ちなみにこの世の犬はみな等しく可愛いので全員SSRです。
ローディングを入れる
export const DogCard = () => {
const [posts, setPosts] = useState([]);
const [renew, setRenew] = useState("");
+ const [isLoading, setIsLoading] = useState(true);
//APIを叩いてpostsにJSONデータを格納
useEffect(() => {
+ setIsLoading(true);
axios
.get("https://dog.ceo/api/breeds/image/random/10")
.then((res) => {
setPosts(res.data.message);
+ setIsLoading(false);
})
.catch((error) => {
console.log(error);
+ setIsLoading(true);
});
}, [setPosts, renew]);
return (
<SDogCard>
<div>
+ {isLoading ? (
+ <div className="spinner-box">
+ <div className="three-quarter-spinner"></div>
+ </div>
+ ) : (
<ul className="dogsList">
{posts.map((post, i) => {
return (
<li key={i} className="dogCard">
<img src={post} alt="犬の画像" className="dogImg" loading="lazy" />
<img src={ssrImg} alt="SSRラベル" className="ssrImg" />
</li>
+ );
})}
</ul>
+ )}
<input
type="button"
value="もう一回!"
onClick={() => setRenew((renew) => renew + 1)}
className="showRenewButton"
/>
</div>
</SDogCard>
);
};
ローディングのぐるぐるが欲しかったので追加しました。
ローディングは下記サイト様を参考にさせていただきました。ありがとうございます!
完成
これで完成です。
あとは好きなだけガチャを回してください!
ちなみにレスポンシブ対応しているので、スマホでも回せます!やったね!
おわりに
ここまで読んでいただきありがとうございました!
ボーナスとしてうちの犬の写真を置いておきます。
かわい~~~~~~ッッッッッ!!!!