概要
CRAでプロジェクトを作成、プロジェクトにPackageを入れて、↑を表示するシンプルなReactコンポーネントの作成を行います。
環境
- Mac
- yarn/npx (CRAのグローバルインストールは非推奨のため)
- TypeScript 3.5+ (オプション)
CRAでベースアプリを作成
# npxの場合
$ npx create-react-app myshader
# yarnの場合
$ yarn create react-app myshader
# npx & typescriptを利用する場合
$ npx create-react-app myshader --template typescript
# yarn & typescriptを利用する場合
$ yarn create react-app myshader --template typescript
大抵の場合は必要ないですが、一応CRAがちゃんとコードを生成している事を確認しておきます。
$ cd myshader
# yarn
$ yarn start
# npm
$ npm start
react-vfxをインストール
react-vfxをインストールします。
併せて、styled-components
も入れておきます。CSSやSCSSまたはSASSが好きな方はインストールしなくても全く問題ないです。
ちなみ、react-vfxはtsで書かれているので、@typesファイルのインストールは不要です。
# yarn
$ yarn add react-vfx styled-components
$ yarn add -D @types/styled-components <-- if you use typescript
# npm
$ npm install react-vfx styled-components
$ npm install -D @types/styled-components <-- if you use typescript
コンポーネントを作成
一番最初の画像を表示するためのシンプルなコンポーネントを作成していきます。
名前はなんでも良いのですが、今回は分かりやすくMyShader.tsx
としました。
本当はフォルダを作るべきなんですが、目的はreact-vfxを試す事なので、src
直下に作りました。
import React from "react";
import * as VFX from "react-vfx";
import styled from "styled-components";
const Content = styled.div`
width: 100vw;
height: 100vh;
`;
const metal = `
uniform vec2 resolution;
uniform float time;
void main()
{
vec2 coord = gl_FragCoord.xy / resolution.xy;
vec2 st = coord;
vec3 line = vec3(0.0);
coord *= 4.;
float len;
for (int i = 0; i < 15; i++) {
len = length(vec2(coord.x, coord.y));
coord.x += cos(coord.y + sin(len)) + cos(time * .07) * 0.2;
coord.y += sin(coord.x + cos(len)) + sin(time * 0.1);
}
len *= cos(len * 0.4);
len -= 10.;
for (float i = 0.0; i < 5.0; i++) {
len += 0.11 / abs(mod(st.x, 1.09 * i) * 200.) * 1.;
}
vec3 color = vec3(cos(len + 0.2) * 1.15, cos(len + 0.1), cos(len - 0.05));
gl_FragColor = vec4(color, 1.0);
}
`;
const MyShader: React.FC = () => {
return (
<>
<VFX.VFXProvider>
<VFX.VFXSpan shader={metal}>
<Content></Content>
</VFX.VFXSpan>
</VFX.VFXProvider>
</>
);
}
export default MyShader;
コード自体は非常にシンプルで、react-vfxをインポート
import * as VFX from "react-vfx";
FragmentShaderをリテラル内に記述して、metalという変数を定義
インポートしたvfxのコンポーネントを使って、metal(FragmentShader)をロード
Content
は表示するためだけのものなので、普通にCSSを書いて、インポートする方がstyled-componentsを使うより簡単かつ楽だと思います。
あとはこれをApp.tsxもしくはApp.jsにインポートして、を記述したのちに、アプリを起動すれば、FragmentShaderで記述されたアニメーションが表示されます。
ちなみに、metal
の部分にShaderToyのコードを移植して、変数名等を修正すれば、簡単に色々なモノを試せます。ただし、公開する場合はライセンスに気をつける必要があります。
react-vfxサンプルページ
react-vfx自体もエフェクトを持っているので、Shaderを書かなくても面白いエフェクトをページに簡単に加える事ができます。
https://amagi.dev/react-vfx/
repo:https://github.com/koji/typescript/tree/master/shadereact
レポジトリを試す場合は下記を実行すれば、動きます。
$ cd shaderreact
$ yarn
$ yarn start
Dev.toに投稿したポストを日本語にして投稿してみました。
元の記事
https://dev.to/kojikanao/use-fragmentshader-with-reactjs-easily-react-vfx-52lm