【AfterEffects】花びらを舞わせるアニメーションを作る
今回はこれを作ります。画像内に花びらを舞わせるアニメーションです。
まずは、花びらを舞わせたい画像を配置しましょう。
画像を配置したら、次は花びらを舞わせる用のコンポジションを作ります。
ここで作る花びらのコンポジションをさっき用意した画像のあるコンポジションに合成しようという感じです。
このコンポジションでは花びらを舞わせるので、舞わせたい花びらを取り込みます。 AdjustmentLayer(調整レイヤー)を新たに追加してエフェクトを加えていきます。
調整レイヤーを選択したらそのレイヤーにCC.ParticleWorldを適用します。
これが花びらを散らしてくれるやつなんですが、まだよくわからないですね。 Particle→ParticleType→TexturedQuardPolygonを選択します。ほかの選択肢もいろいろ試してみればわかるけど、これはどんな形でParticleを扱いたいかという選択。
次に舞わせたい対象を選択します。 Partile→Texture→TextureLayerから舞わせたいものを選択しましょう。今回はさっき追加した花びらの画像を舞わせたいので、取り込んだ画像を選択します。
この時点で再生するとこんな風になります。
片鱗が見えてきましたね。今のままの形だと「舞う」とは程遠いため、これを舞っているようにいろんな値をいじっていきます。 参考までにいじった値を載せておきます。
- BirthRate・・・0.1 - Longevity・・・5.91 - Procedure PositionY・・・-0.34 RadiusX・・・1.745 - Physics Animation・・・Twirl Velocity・・・0.41 Gravity・・・0.1 Resistance・・・1.5 - Particle BirthSize・・・0.22 DeathSize・・・0.34 SizeVariation・・・58 MaxOpacity・・・100
こういう値はいろいろいじってみて理想の動きになるか都度チェックしていくといいです。 値を調整したら、画像を配置したコンポジションに今作った花びらのコンポジションを入れましょう。
再生すると、画像内に花びらが舞っているはずです。 花びらの色味がちょっと微妙だったので、花びらの方のコンポジションに調整レイヤーを追加して色味を調整します。
普通にカラーバランスでいいかな。
これで完成です。
【AfterEffects】バチバチなテキストアニメーションを作る
今回はこれを作ります。 saberというプラグインを使うので、持っていない人はこれを機に使ってみるといいんじゃないでしょうか。プラグインを使うだけで簡単にかっこいいアニメーションを作ることができます。インストールは下記から。
まずは、バチバチにさせたいテキストを置きましょう。今回は「ART」でいきます!
そしたらLayer→AutoTraceと進んで、文字をトレースしてやります。
そうすると、文字をかたどった線みたいなのができるはずです。
これにSaberを当てていきます。EffectsからSaberを選択して追加しましょう。
かっこいいですね。今のままだと、文字をかたどったエフェクトになっていないので、レイヤーマスクにします。 CustomizeCore→CoreType→LayerMaskを選択しましょう。
ちょっと見た目が変わったはずです。
デフォルトで選択されているPresetはSelectだけど、これをArcReactorにします。
するとこんな風になる。
良い感じですね。ちなみに用意されているPresetはほかにもたくさんあるからいろいろ試してみると面白いです。 これだけでも良いですが、若干の色味も欲しいですね。ちょっと黄色っぽいものを追加しますかね。
Effectsからvegaを追加しました。 追加するとちょっとだけ黄色がかった何かが見て取れると思います。 これで完成。
【AfterEffects】水のようなテキストアニメーションを作る
作るもの
今回作るものはこれ。水のようなテキストアニメーションを作っていこうと思う。
まずは、表示させたいテキストを作っていきましょう。テキストレイヤーを新たに追加して、適当にTEXTにしておきます。
次に背景!白っぽいものにしたいので、真っ白のものを追加します。
テキストレイヤーの下に背景を入れてこんな感じです。後は、これにアニメーションをつけていけばいいだけですね。
Adjustment Layerを追加する。普段英語のもの使っているから日本語バージョンのあんまり覚えてないけど、確か調整レイヤーだった気がする。なので、日本語バージョンを使っているなら調整レイヤーを追加しましょう。
調整レイヤーを追加したら、「CC.MrMercury」を追加します。こいつが画像を液体チックにしてくれます。
追加した時点で再生するとこんな感じです。 画像全体に液体のアニメーションがいきわたっていないので、いきわたらせるようにします。
以下の項目なんかの数値をいじるとちょっと良い感じになります。いろいろ数値をいじってみるといいです。
- RadiusX
- RaduisY
- velociy
- Birthrate
このままでもよいですが、色味が欲しいので水っぽい画像を追加します。
水の画像を下の方のレイヤーにいれます。
白の後ろに青っぽい色のものが出ました。画像使わないでも普通にsolidLaterでいいかもしれないね。
動画で見たい方は動画もあります。
gqlgenチュートリアルを試す
今更な感じもあるけど、改めてgqlgenのチュートリアルをやってみる。ドキュメント通りにやればサクッと試せます。
チュートリアル
https://gqlgen.com/getting-started/ チュートリアル見ればできるので、端折って書く。ここではコメント的なことを書いておく。 チュートリアルで作るschema.graphqlは以下。
// schema.graphql type Todo { id: ID! text: String! done: Boolean! user: User! } type User { id: ID! name: String! } input NewTodo { text: String! userId: String! } type Query { todos: [Todo!]! } type Mutation { createTodo(input: NewTodo!): Todo! }
これを元に以下コマンドでgqlgenを実行する。
$ go run github.com/99designs/gqlgen init
すると、models_gen.goにschema.graphqlで定義したものから以下の構造体が作成される。
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. package gqlgen_todos type NewTodo struct { Text string `json:"text"` UserID string `json:"userId"` } type Todo struct { ID string `json:"id"` Text string `json:"text"` Done bool `json:"done"` User *User `json:"user"` } type User struct { ID string `json:"id"` Name string `json:"name"` }
QueryやMutationは以下のように定義したので、resolver.goを見るとそれらの関数が定義されている。
// scheme.graphql type Query { todos: [Todo!]! } type Mutation { createTodo(input: NewTodo!): Todo! }
// resolver.go func (r *mutationResolver) CreateTodo(ctx context.Context, input NewTodo) (*Todo, error) { panic("not implemented") } type queryResolver struct{ *Resolver } func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) { panic("not implemented") }
このresolverに作られた関数をいじってやればOK。 チュートリアルを眺めてみると、このtodoのAPIの要件としては、ユーザーのIDが渡された時だけユーザー情報を返したいらしい。 だけど、このschemaから作られるのは以下の関数。
func (r *mutationResolver) CreateTodo(ctx context.Context, input NewTodo) (*Todo, error) { panic("not implemented") }
戻り値の*TodoのTodoはmodels_gen.go
にある以下のTodo構造体なので、Userを返さないといけない。
type Todo struct { ID string `json:"id"` Text string `json:"text"` Done bool `json:"done"` User *User `json:"user"` } // Userはこれ type User struct { ID string `json:"id"` Name string `json:"name"` }
でもUser情報を持っているUser構造体はユーザーIDが渡された時にだけ返したいっぽいので、schme.graphqlで定義されたTodo構造体ではなく、別のTodo構造体を作る。resolverでは、その新たに作った構造体を使う。
追加するには、gqlgen.yml
にmodelを追加すれば使えるようになるらしいので追加。
models: Todo: model: github.com/gqlgen-todos.Todo
後はこのパスにTodo構造体を作る。
package gqlgen_todos type Todo struct { ID string Text string Done bool UserID string }
コマンド実行
$ go run github.com/99designs/gqlgen
models_gen.goには新たに既存のTodo構造体がなくなっています。自分で新しくTodo構造体を作成したためですね。
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. package gqlgen_todos type NewTodo struct { Text string `json:"text"` UserID string `json:"userId"` } type User struct { ID string `json:"id"` Name string `json:"name"` }
Resolverを新たな定義によって更新するため、以下コマンドを実行
rm resolver.go go run github.com/99designs/gqlgen
これを実行すると以下のresolverが作成されます。 最終的にAPIとして返すのは、schema.graphqlで定義したTodoだけど、resolverとして扱うのはさっき新たに作ったTodoです。
// schema.graphql type Todo { id: ID! text: String! done: Boolean! user: User! }
// todo.go type Todo struct { ID string Text string Done bool UserID string }
返す時の流れとしてはresolver→schema.graphql
となるはずなので、どこかで新たに作った構造体を元にschema.graphqlのTodoに合うようにしなければなりません。
新たに作成されたresolverを見てみると以下のようになっています。
package gqlgegn_todos import ( "context" ) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES. type Resolver struct{} func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } func (r *Resolver) Todo() TodoResolver { return &todoResolver{r} } type mutationResolver struct{ *Resolver } func (r *mutationResolver) CreateTodo(ctx context.Context, input NewTodo) (*Todo, error) { panic("not implemented") } type queryResolver struct{ *Resolver } func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) { panic("not implemented") } type todoResolver struct{ *Resolver } func (r *todoResolver) User(ctx context.Context, obj *Todo) (*User, error) { panic("not implemented") }
注目すべきは、新たに追加されたUser関数です。
func (r *todoResolver) User(ctx context.Context, obj *Todo) (*User, error) { panic("not implemented") }
このUser関数がschema.graphqlで定義したTodo構造体のフィールドUserを担ってくれるようです。自動生成されるモデルじゃなくて自分で作ったものモデル使うのもいいけど、最終時にはschema.graphqlで定義したものに合うように実装しろということですね。 generated.goをみるとinterfaceとして定義されています。
type TodoResolver interface { User(ctx context.Context, obj *Todo) (*User, error) }
おそらくこのUser関数の呼び出しは自動生成されたgenerated.goでやってくれるのかと思いますが、中身を見てもどうなっているのかよくわからん。 で、チュートリアルではこんな感じになっています。
package gqlgen_todos import ( context "context" "fmt" "math/rand" ) type Resolver struct { todos []*Todo } func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } func (r *Resolver) Todo() TodoResolver { return &todoResolver{r} } type mutationResolver struct{ *Resolver } func (r *mutationResolver) CreateTodo(ctx context.Context, input NewTodo) (*Todo, error) { todo := &Todo{ Text: input.Text, ID: fmt.Sprintf("T%d", rand.Int()), UserID: input.UserID, } r.todos = append(r.todos, todo) return todo, nil } type queryResolver struct{ *Resolver } func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) { return r.todos, nil } type todoResolver struct{ *Resolver } func (r *todoResolver) User(ctx context.Context, obj *Todo) (*User, error) { return &User{ID: obj.UserID, Name: "user " + obj.UserID}, nil }
これでgo run server/server.go
してplaygroundでクエリを打ってみると結果が得られます。
自動生成されたファイルが結構色々やっちゃってくれちゃうから何をどうやっているのかは中身の実装を詳しく見ないとわからないね。
webpackで本番ビルド時にfirebaseの環境変数を設定する
reactのアプリケーションを確認していたら、webpackの環境変数設定でおかしなことになっていたからメモ。
このアプリケーションはfirebaseで運用しているんだけど、firebaseで設定した環境変数をうまく取得できていなかった。やりたいこととしてはfirebase(本番環境)用にbuildする時にはfirebaseで設定した環境変数を参照してbuildできること。
続きを読むvueのサンプルテストを書いてみる
vueとgoでポートフォリオ作ったんだけど、vueのテストってどうやって書くんだろう・・・ということでちょっと見てみる。
vue-test-utilsを使ってみる
以下のvue公式のサンプルを試してみよう。
vue-test-utils は Vue コンポーネントを隔離してマウントし、必要な入力(プロパティ、注入、そしてユーザイベント)をモックし、そして出力(描画結果、カスタムイベントの発行)を検証することでテストします。
なるほどどうやらモックを作ってそのモックを通してテストするようだ。
マウントされたコンポーネントは Wrapper の内部に返されます。これは、基の Vue コンポーネントインスタンスを操作、トラバース、クエリ処理するための多くの便利なメソッドを公開しています。
Wrapperってやつがコンポーネントをなんかうまくやってくれるらしい。
なんかWrapperっていうのを使うとコンポーネントをラップしてくれるのかな。で、テストではそのラップされたものを使えと。コード見る感じそんな気がする 。
import { mount } from '@vue/test-utils' import Counter from './counter' // コンポーネントがマウントされ、ラッパが作成されます。 const wrapper = mount(Counter)
test-utilsのmount関数を使ってコンポーネントをラップ。そしてこのラップされえたwrapperをいじっていくんやな。
import { mount } from '@vue/test-utils' import Counter from './counter' describe('Counter', () => { // コンポーネントがマウントされ、ラッパが作成されます。 const wrapper = mount(Counter) console.log(wrapper.html()) // => <div><span class="count">0</span> <button>Increment</button></div> })
mountで作成されたラッパーはラッパーとしての関数を持っているから例えば、.html()
なんかすると、そのコンポーネントが持っているhtmlを返してくれる。
記事通りに進めてこんな感じに書くと、テストは通るね。
import { mount } from '@vue/test-utils' import Counter from './counter' describe('Counter', () => { // コンポーネントがマウントされ、ラッパが作成されます。 const wrapper = mount(Counter) it('renders the correct markup', () => { expect(wrapper.html()).toContain('<span class="count">0</span>') }) // 要素の存在を確認することも簡単です it('has a button', () => { expect(wrapper.contains('button')).toBe(true) }) })
$ npm test Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 0.527s
このexpect
とかtoBe
なんていうメソッドはJestに備わっているものっぽい。
テストするときにはこのJestのメソッドとvue-test-utilsのメソッドを組み合わせてやっていく感じか。なんかテストコード見てるとRspec感がなくもない。
jestは拡張子でテストファイル判断。
デフォルトでは、Jest はプロジェクト全体で .spec.js または .test.js 拡張子を持つすべてのファイルを再帰的に取得します。これがあなたのニーズに合わない場合は、package.json ファイルの config セクションでtestRegex を変更することが可能です。
ユーザのインタラクションをシミュレーションする
このサンプルのコードにはボタンをクリックするとdataとして持っている数値をincrementするっていう実装があるんだけど、こんなのもテストできるらしい。
import { mount } from '@vue/test-utils' import Counter from './counter' describe('Counter', () => { // コンポーネントがマウントされ、ラッパが作成されます。 const wrapper = mount(Counter) it('button click should increment the count', () => { expect(wrapper.vm.count).toBe(0) const button = wrapper.find('button') button.trigger('click') expect(wrapper.vm.count).toBe(1) }) })
wrapper.vm.count
でvueインスタンスのdataであるcountにアクセスしてるのね。インクリメントするために、ボタンのラッパである .trigger() を呼び出すことでクリックしている。
gitlabのCIで起きたエラーをメモしておく
gitlabのCIで起きたエラーをメモしておく。
続きを読むgomailを使ってローカルではmailhog・本番(Heroku)ではsendgridでメール送信する
メール送信機能をgoのアプリケーションにつけようと思ったけど、どうやってやろうかなー、と。で、ローカルではdockerでメールサーバー用意して、本番ではsendgridで行うようにした。
メール送信のパッケージにはgomailというものを使ってやるかな。
続きを読むelmでハローワールド
elmでハローワールドしよ。
elmインストール
下記のページから自分のパソコンにあったバイナリを入れる。
elmプロジェクト作成
$ elm init
これでelmのプロジェクトが作成される。
. ├── elm.json └── src
ローカルサーバー起動
$ elm reactor
これでローカルのサーバーが立ち上がる。localhost:8000にアクセスするとどんなもんか見れる。
パッケージインストール
パッケージのインストールは以下のコマンドで行える。パッケージはelm.json
に記述されていくよ。
$ elm install elm/http $ elm install elm/json
これ依存関係あった場合、知らせてくれるのね。親切。
I found it in your elm.json file, but in the "indirect" dependencies. Should I move it into "direct" dependencies for more general use? [Y/n]: Y
HelloWorld表示
src配下にファイルを作ってハローワールドする。
import Html exposing (..) // Htmlパッケージの全ての関数をimport main = text "Hello world!"
これで、elm reactor
して画面を確認。
画面上に表示されているのって、ディレクトリなんだね。で、そのディレクトリに今回作成したファイル名(画像でいえばhello_world.elm)があるからそれをクリックするとHello world!と表示された。
ワードプレスの速度改善をしたかった- GTmetrixとLightHouseで改善する -
ワードプレスで運営しているサイトのSEOが気になったので、久しぶりに色々みてみる。
続きを読むgo・gin・gormとdockerで作ったAPIをHerokuで動かす
個人的にAPIを作ったけど、やっぱり作ったらどこかにデプロイしたい。
当初は、 GKE + CloudSQLの構成でやろうと思ったけど、結構料金かかるみたいだから断念。Kubernetes試してみたかったんだけどな。そもそも、CloudSQLが割と料金かかる。
RDBは無料で使えるようなものはほとんどないっぽい・・悲しい・・・
ということで、APIはHerokuに置いてしまうことにした。開発環境はDockerで作ったから、HerokuでもDocker運用する。
続きを読むLaravelからGCPのCloudSQLに接続できるようにする
AppEngineにlaravelアプリケーションをデプロイしても、DB接続とか面倒なのでメモ。
続きを読む