Open40

Webポーフォリ作業日記

にー兄さんにー兄さん

Webポーフォリの作成作業をしているけど、なんだかんだ知見がたまってきてる気がするのでメモしていく
一部を記事にできたりするかもだしね

にー兄さんにー兄さん

環境は以下

  • Nuxt 3.0.0 (SSG)
  • Vite
  • Babylon.js 5.39.0
  • docker desktop for Windows / docker-compose
にー兄さんにー兄さん

Nuxt3で@nuxtjs/google-fontsを使ってGoogleFontを読み込む方法

yarn add -D @nuxtjs/google-fonts@3

で指定のバージョンのパケをインストールする
nuxt.config.tsに以下のように記述

nuxt.config.ts
import { defineNuxtConfig } from 'nuxt/config';
import '@nuxtjs/google-fonts';

export default defineNuxtConfig({
  // ...
  modules: ['@nuxtjs/google-fonts'],
  googleFonts: {
    display: 'swap',
    families: {
      Roboto: true,
    },
  },
  // ...
});

にー兄さんにー兄さん

そもそもgoogle fontsパケがNuxt3への対応版がプレリリースらしい
巷の記事や公式docsではbuildModulesに書けって出てくるけど型エラーになった。
Nuxt3の公式docsではmodulesにしろって書いてあったのと、googleFonts自体も型エラーになるので適切にインポートする必要がある
https://nuxt.com/docs/migration/configuration/#migration-1

にー兄さんにー兄さん

唐突に設計をし始めるなどした

にー兄さんにー兄さん

CAに基づいてControllerやらPresenterやらも一応書いてみたが、Vueでコンポーネントでどう実装するのかまだイメージがついていないので、ここは厳密にはなくなるかもしれない
Composableになる気がする

にー兄さんにー兄さん

当初はポーフォリに設計を導入する必要はないと考えていた
開発スピードを上げたかったのと、別にサービス作ってるわけじゃないからビジネスルールなんてないやろみたいな

しかしよくよく考えてみればポーフォリって長い間メンテすることになるし
途中で採用している個々の技術は変化するかもしれない
例えばNuxt3こそ最近出てきた技術なだけでn年後にはまた別のバージョンやらフレームワークが良いとされるかもしれない
Babylon.jsだって長い間使い続けないかもしれない
採用予定のContentfulも、将来的に買収やらサ終やらで乗り換えるかもしれないし、そもそもまだ使ってないから決定を遅延したい
そう思うと一部の技術をすぐ切り替えられるようにするのは価値があるのかなぁと思った

あと普通にポーフォリにだってビジネスルールがある
私自身の情報がこのソフトウェアの価値であるためだ
それは詳細に依存する必要のないPlain Oldなデータにできるるため、フレームワークやライブラリが変わったとしても影響されない

とうことで、なるべくビジネスルールと詳細は分けようと思う
CleanArchitectureをめっちゃしっかりやらなくてもいいので、ひとまず意識したいし
後々アーキテクチャもリファクタしていけるようにメモしておく

にー兄さんにー兄さん

背景アートワークのスタイリング、考えていた実装方法を試したところうまくいったみたい

にー兄さんにー兄さん

これやるにあたって前までapp.vueが汚かったんですけど、グローバルcssとかLayoutsとか整備しました

にー兄さんにー兄さん

あとデバッガの設定もしました
VSCOdeほんとすごいな、docker越しでも全然気にならずに普通にデバッガが動いたわ

にー兄さんにー兄さん

生成されたシェーダコードはこちら

// Vertex shader
precision highp float;

// Attributes
attribute vec2 position;

// Uniforms
uniform float u_Constant;
uniform vec2 u_UVScale;
uniform vec2 u_UVOffset;

// Varyings
varying vec2 v_position;

// Entry point
void main(void) {

  // Position3D
  vec4 xyzw = vec4(position, 0.0, u_Constant).xyzw;

  // VertexOutput
  gl_Position = xyzw;
  v_position = position;
}

// Fragment shader
precision highp float;

// Uniforms
uniform float u_Constant;
uniform vec2 u_UVScale;
uniform vec2 u_UVOffset;

// Varyings
varying vec2 v_position;

// SimplexPerlin3D
const float SKEWFACTOR = 1.0 / 3.0;
const float UNSKEWFACTOR = 1.0 / 6.0;
const float SIMPLEX_CORNER_POS = 0.5;
const float SIMPLEX_TETRAHADRON_HEIGHT = 0.70710678118654752440084436210485;
float SimplexPerlin3D(vec3 P) {
  P.x = P == vec3(0., 0., 0.) ? 0.00001 : P.x;
  P *= SIMPLEX_TETRAHADRON_HEIGHT;
  vec3 Pi = floor(P + dot(P, vec3(SKEWFACTOR)));
  vec3 x0 = P - Pi + dot(Pi, vec3(UNSKEWFACTOR));
  vec3 g = step(x0.yzx, x0.xyz);
  vec3 l = 1.0 - g;
  vec3 Pi_1 = min(g.xyz, l.zxy);
  vec3 Pi_2 = max(g.xyz, l.zxy);
  vec3 x1 = x0 - Pi_1 + UNSKEWFACTOR;
  vec3 x2 = x0 - Pi_2 + SKEWFACTOR;
  vec3 x3 = x0 - SIMPLEX_CORNER_POS;
  vec4 v1234_x = vec4(x0.x, x1.x, x2.x, x3.x);
  vec4 v1234_y = vec4(x0.y, x1.y, x2.y, x3.y);
  vec4 v1234_z = vec4(x0.z, x1.z, x2.z, x3.z);
  Pi.xyz = Pi.xyz - floor(Pi.xyz * (1.0 / 69.0)) * 69.0;
  vec3 Pi_inc1 = step(Pi, vec3(69.0 - 1.5)) * (Pi + 1.0);
  vec4 Pt = vec4(Pi.xy, Pi_inc1.xy) + vec2(50.0, 161.0).xyxy;
  Pt *= Pt;
  vec4 V1xy_V2xy = mix(Pt.xyxy, Pt.zwzw, vec4(Pi_1.xy, Pi_2.xy));
  Pt = vec4(Pt.x, V1xy_V2xy.xz, Pt.z) * vec4(Pt.y, V1xy_V2xy.yw, Pt.w);
  const vec3 SOMELARGEFLOATS = vec3(635.298681, 682.357502, 668.926525);
  const vec3 ZINC = vec3(48.500388, 65.294118, 63.934599);
  vec3 lowz_mods = vec3(1.0 / (SOMELARGEFLOATS.xyz + Pi.zzz * ZINC.xyz));
  vec3 highz_mods = vec3(1.0 / (SOMELARGEFLOATS.xyz + Pi_inc1.zzz * ZINC.xyz));
  Pi_1 = (Pi_1.z < 0.5) ? lowz_mods : highz_mods;
  Pi_2 = (Pi_2.z < 0.5) ? lowz_mods : highz_mods;
  vec4 hash_0 =
      fract(Pt * vec4(lowz_mods.x, Pi_1.x, Pi_2.x, highz_mods.x)) - 0.49999;
  vec4 hash_1 =
      fract(Pt * vec4(lowz_mods.y, Pi_1.y, Pi_2.y, highz_mods.y)) - 0.49999;
  vec4 hash_2 =
      fract(Pt * vec4(lowz_mods.z, Pi_1.z, Pi_2.z, highz_mods.z)) - 0.49999;
  vec4 grad_results =
      inversesqrt(hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2) *
      (hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z);
  const float FINAL_NORMALIZATION = 37.837227241611314102871574478976;
  vec4 kernel_weights =
      v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
  kernel_weights = max(0.5 - kernel_weights, 0.0);
  kernel_weights = kernel_weights * kernel_weights * kernel_weights;
  return dot(kernel_weights, grad_results) * FINAL_NORMALIZATION;
}

// FragmentOutput
#include <helperFunctions>

// Entry point
void main(void) {

  // Multiply
  vec2 output4 = v_position * u_UVScale;

  // Add
  vec2 output3 = output4 + u_UVOffset;

  // VectorMerger
  vec3 xyz1 = vec3(output3, 0.0).xyz;

  // SimplexPerlin3D
  float output2 = SimplexPerlin3D(xyz1);

  // Remap
  float output1 = 0.0 + (output2 - -1.0) * (1.0 - 0.0) / (1.0 - -1.0);

  // Gradient
  vec3 gradientTempColor =
      vec3(0.10980392156862745, 0.6039215686274509, 0.807843137254902);
  float gradientTempPosition;
  gradientTempPosition =
      clamp((output1 - 0.0) / (0.41 - 0.0), 0.0, 1.0) * step(1.0, 3.0);
  gradientTempColor =
      mix(gradientTempColor,
          vec3(0.29411764705882354, 0.6274509803921569, 0.3058823529411765),
          gradientTempPosition);
  gradientTempPosition =
      clamp((output1 - 0.41) / (0.64 - 0.41), 0.0, 1.0) * step(2.0, 3.0);
  gradientTempColor =
      mix(gradientTempColor,
          vec3(0.6078431372549019, 0.13333333333333333, 0.40784313725490196),
          gradientTempPosition);
  gradientTempPosition =
      clamp((output1 - 0.64) / (1.0 - 0.64), 0.0, 1.0) * step(3.0, 3.0);
  gradientTempColor =
      mix(gradientTempColor,
          vec3(0.611764705882353, 0.18823529411764706, 0.18823529411764706),
          gradientTempPosition);
  vec3 output0 = gradientTempColor;

  // FragmentOutput
  gl_FragColor = vec4(output0, 1.0);
#ifdef CONVERTTOLINEAR0
  gl_FragColor = toLinearSpace(gl_FragColor);
#endif
#ifdef CONVERTTOGAMMA0
  gl_FragColor = toGammaSpace(gl_FragColor);
#endif
}
にー兄さんにー兄さん

黒ベースでグラデーションを載せてみる
ちょっとカッコよくなったんじゃなかろうか

にー兄さんにー兄さん

地味にカーソル位置に反応してUVがずれるインタラクションを仕込んである。ちょっと地味すぎるかもだけど

にー兄さんにー兄さん

カーソルはVueUseを使ってカーソル位置をrefで受け取り反映している
ただスクロール位置も変わると画面位置相対ではないので工夫しなきゃな

にー兄さんにー兄さん

PerlinNoiseのスクロールをスクリーンUVではなくz値にしたらいい感じになった、うれしい

にー兄さんにー兄さん

Figmaで図形パターンを配置してみたけど、思ったよりもかっこいい

こんな感じで伸ばしていく予定

にー兄さんにー兄さん

伸ばしていくかもちょっと悩み中
最初のランディングページはあの画面だけで、そこから画面遷移でもいいのかな