
制作ノート: PUNCH Portfolio & SOLANI Portfolio
制作ノート第二弾です。
イラストレーター/グラフィックデザイナーのパンチさん、イラストレーターのSOLANIさんのポートフォリオサイトを制作させて頂きました。パンチさんとSOLANIさんもお仕事を一緒にされたりしていて仲が良いので、公開時期もたまたま被りそうだったのでどうせなら同時公開同時告知をしようとなり、先日公開に至りました。この記事では二つのサイトのデザインや実装、その意図についてお話します。まずはお二人のポートフォリオサイトをご覧ください。
おしらせ
— Keita Yamada (@P5_keita) November 7, 2022
2名のクリエイターのポートフォリオサイトを同時公開。
イラストレーター/デザイナーのパンチさん(@punch6789 )、イラストレーターのSOLANIさん(@drawing_account )のポートフォリオサイトを制作させて頂きました。
PUNCHhttps://t.co/eBVocDaXRa
SOLANIhttps://t.co/fCbFWwQpGl pic.twitter.com/ogV7cFeEEv
Topページ
Topページの在り方についてはずっと悩んでいました。そもそもTopページって役割が曖昧なんですよね。他のページは作品を一覧したり、その人の情報を見れたりと役割がはっきりしていますが、Topページには明確な役割が存在しません。色々悩んだ結果、ポートフォリオサイトのTopページの役割は「おっ!」っと思わせることだと考えました。特別な印象を与えつつ、役割的には画集の表紙と目次を合わせたような存在にしようと思い至り、現在の構成になりました。


Projects & Artworksページ
二つのサイトには共通してProjectsページとArtworksページがありますが役割は若干異なります。パンチさんのProjectsページはお仕事の実績一覧、Artworksページは自主制作の一覧になっており、SOLANIさんのProjectsページはお仕事と自主制作の一覧、Artworksページは全Projectの全画像を一覧できるページにしました。このあたりはお二人の活動内容や掲載する作品の数によって判断しています。


二つのProjectsページでは似た処理で演出を施しました。パンチさんのProjectsページではカーソルのY座標が画像領域内に入っている場合にタイトルとメタ情報を表示、SOLANIさんのProjectsページではカーソルがタイトル領域内に入っている場合に左側に対応する画像を表示しています。
ここで一工夫をしています。このようなマウスホバー時の演出はCSSであれば:hover疑似要素、JavaScriptであればmouseenterイベントなどを使って実装しますが、この二つはカーソルを動かさないと有効になりません。カーソルを動かさずスクロールしてカーソルと要素が重なった場合は動かないんですね。なのでJavaScriptでrequestAnimationFrameを使い、毎フレームカーソルと要素の交差判定をすることによってこのスムーズな演出を実装しました。コードは以下のようになっています。Pointerは自作のカーソル座標取得用クラス、onMouseEnterでカーソルと要素が交差したときの処理、onMouseLeaveで交差しなくなったときの処理を記述しています。
const x = Pointer.x
const y = Pointer.y
for (let i = 0; i < this.numItems; i++) {
const $item = this.$items[i]
const { left, right, top, bottom } = $item.getBoundingClientRect()
if (x >= left && x <= right && y >= top && y <= bottom) {
this.onMouseEnter(i)
} else {
this.onMouseLeave(i)
}
}
Project詳細ページ
どちらのProject詳細ページも画像を横スクロールで見られるようにしました。パンチさんの場合は「+」ボタンを押せばテキスト情報が消え画面いっぱいに画像が広がり、SOLANIさんの場合は最初から画像を大きく表示しています。テキストのボリュームなどの違いによって作り分けています。いい絵が画面いっぱいに広がって横に並んでいると脳が悦ぶので、脳が悦ぶ方へ方へと舵を切りました。


Artwork詳細ページ
どちらのArtwork詳細ページも画像が主役なので、できるだけシンプルなUIで画像を一覧できるページにしました。カーソルを動かさなくてもキーボードの左右矢印キーで画像を切り替えることができます。
Projectページとは違うUI、別の見方を提供することで、仕事の依頼を検討しようと見に来た人にも、ふらっと絵を見に来た人にも合うようなサイトにしたいと考えました。


Grid System
どちらのサイトもGridを使いレイアウトをしています。
パンチさんのサイトではカラム数: 12、左右マージン: 10px、SOLANIさんのサイトではカラム数: 12、左右マージン: 80pxで作りました。下の画像はデザインツール上のグリッドではなく実装側で表示しているグリッドです。開発時はDキーを押すことでこのグリッドが表示され、グリッドを表示しつつブラウザの幅を変えながらレスポンシブデザインの調整をしました。




振り返り
超楽しかった。